﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.ModifingManager;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.Widgets;
using System.Windows.Media.Imaging;
using SHomeWorkshop.LunarConcept.Converters;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;
using SHomeWorkshop.LunarConcept.Enums;

namespace SHomeWorkshop.LunarConcept.Controls
{
    /// <summary>
    /// 创建时间：2011年12月26日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：用以承载各Widget的编辑器。
    /// 基本结构：总封装编辑器（EditorManager）→本编辑器（PageEditor）→
    ///           外层容器（baseCanvas)→控制模拟物（如画线时的显示虚线）、内容器（mainCanvas）→各部件。
    ///           
    ///           真正用以放置部件的是内容器（mainCanvas）。
    ///           ——本类继承自Decorator，内部嵌入了个外层容器（baseCanvas），外层容器内部又嵌入了一个内容器（mainCanvas）。
    ///           
    /// ★★注意：作为基本功能类，此类与EdiorManager类一样，都不应直接调用“注册修改项”的代码。
    ///           ——所有“修改项”的注册都应由“自定义命令”的Execute()方法来调用。
    /// </summary>
    public class PageEditor : AdornerDecorator
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态构造方法]
        /// </summary>
        static PageEditor()
        {
            selectedBorderColor = new SolidColorBrush(Color.FromArgb(0xff, 0xff, 0xc4, 0x5d));

            //初始化页面菜单
            pageContextMenu = new ContextMenu();

            MenuItem miAddPageEditor = new MenuItem() { Header = "添加页(_A)", InputGestureText = "Ctrl + Shift + P" };
            miAddPageEditor.Command = Commands.InsertNewPageEditorCommand.RoutedUICmd;
            pageContextMenu.Items.Add(miAddPageEditor);

            MenuItem miCopyPageEditor = new MenuItem() { Header = "复制页(_D)", InputGestureText = "Ctrl + Alt + P" };
            miCopyPageEditor.Command = Commands.InsertPageCopyEditorCommand.RoutedUICmd;
            pageContextMenu.Items.Add(miCopyPageEditor);

            pageContextMenu.Items.Add(new Separator());

            #region 添加ShapeWidget的相关菜单按钮
            //StackPanel spWidgets = new StackPanel();
            //spWidgets.Orientation = Orientation.Horizontal;

            //Thickness margin = new Thickness(10, 0, 10, 0);

            //Image imgInsertEllipse = new Image() { Margin = margin, Height = 24, Width = 24, };
            //imgInsertEllipse.Source = Globals.MainWindow.FindResource("DIEllipse") as DrawingImage;

            //Image imgInsertRectangle = new Image() { Margin = margin, Height = 24, Width = 24, };
            //imgInsertRectangle.Source = Globals.MainWindow.FindResource("DIRectangle") as DrawingImage;

            //Image imgInsertRhomb = new Image() { Margin = margin, Height = 24, Width = 24, };
            //imgInsertRhomb.Source = Globals.MainWindow.FindResource("DIRhomb") as DrawingImage;

            //Image imgInsertTriangle = new Image() { Margin = margin, Height = 24, Width = 24, };
            //imgInsertTriangle.Source = Globals.MainWindow.FindResource("DITriangle") as DrawingImage;


            //spWidgets.Children.Add(imgInsertRectangle);
            //spWidgets.Children.Add(imgInsertRhomb);
            //spWidgets.Children.Add(imgInsertEllipse);
            //spWidgets.Children.Add(imgInsertTriangle);

            //MenuItem miInsertShapeWidgets = new MenuItem() { Header = spWidgets, };
            //pageContextMenu.Items.Add(miInsertShapeWidgets);
            #endregion

            MenuItem miCut = new MenuItem() { Header = "剪切(_X)", InputGestureText = "Ctrl + X" };
            miCut.Command = Commands.CutCommand.RoutedUICmd;

            MenuItem miCopy = new MenuItem() { Header = "复制(_C)", InputGestureText = "Ctrl + C" };
            miCopy.Command = Commands.CopyCommand.RoutedUICmd;

            MenuItem miPaste = new MenuItem() { Header = "粘贴(_V)", InputGestureText = "Ctrl + V" };
            miPaste.Command = Commands.PasteCommand.RoutedUICmd;

            MenuItem miSelectAll = new MenuItem() { Header = "全选(_A)", InputGestureText = "Ctrl + A" };
            miSelectAll.Command = Commands.SelectAllWidgetsInPageEditorCommand.RoutedUICmd;

            pageContextMenu.Items.Add(miCut);
            pageContextMenu.Items.Add(miCopy);
            pageContextMenu.Items.Add(miPaste);
            pageContextMenu.Items.Add(miSelectAll);

            pageContextMenu.Items.Add(new Separator());

            MenuItem miSetPageHorizontal = new MenuItem() { Header = "横向(_H)", };
            miSetPageHorizontal.Command = Commands.SetPaperHorizontalCommand.RoutedUICmd;

            MenuItem miSetPageVertical = new MenuItem() { Header = "纵向(_H)", };
            miSetPageVertical.Command = Commands.SetPaperVerticalCommand.RoutedUICmd;

            pageContextMenu.Items.Add(miSetPageHorizontal);
            pageContextMenu.Items.Add(miSetPageVertical);

            pageContextMenu.Items.Add(new Separator());

            MenuItem miSetPageSizePaper = new MenuItem() { Header = "纸张尺寸(_P)", };
            MenuItem miSetPageSizeA3 = new MenuItem() { Header = "A_3", CommandParameter = "A3", };
            MenuItem miSetPageSizeA4 = new MenuItem() { Header = "A_4", CommandParameter = "A4", };
            MenuItem miSetPageSizeA5 = new MenuItem() { Header = "A_5", CommandParameter = "A5", };
            MenuItem miSetPageSizeA6 = new MenuItem() { Header = "A_6", CommandParameter = "A6", };

            miSetPageSizePaper.Items.Add(miSetPageSizeA3);
            miSetPageSizePaper.Items.Add(miSetPageSizeA4);
            miSetPageSizePaper.Items.Add(miSetPageSizeA5);
            miSetPageSizePaper.Items.Add(miSetPageSizeA6);

            MenuItem miSetPageSizeSlide = new MenuItem() { Header = "幻灯片尺寸(_S)", ToolTip = "自动横向", };
            MenuItem miSetPageSizeSlide640_480 = new MenuItem() { Header = "_640*480", CommandParameter = "Slide640*480", };
            MenuItem miSetPageSizeSlide800_600 = new MenuItem() { Header = "_800*600", CommandParameter = "Slide800*600", };
            MenuItem miSetPageSizeSlide1024_768 = new MenuItem() { Header = "_1024*768", CommandParameter = "Slide1024*768", };

            miSetPageSizeSlide.Items.Add(miSetPageSizeSlide640_480);
            miSetPageSizeSlide.Items.Add(miSetPageSizeSlide800_600);
            miSetPageSizeSlide.Items.Add(miSetPageSizeSlide1024_768);

            MenuItem miSetPageSizePortableDevice = new MenuItem() { Header = "移动设备尺寸(_P)" };
            MenuItem miSetPageSizeXxhdpi = new MenuItem() { Header = "_xxhdpi,1920*1080", CommandParameter = "xxhdpi", };
            MenuItem miSetPageSizeXhdpi = new MenuItem() { Header = "_xhdpi,1280*720", CommandParameter = "xhdpi", };
            MenuItem miSetPageSizeHdpi = new MenuItem() { Header = "_hdpi,480*800", CommandParameter = "hdpi", };
            MenuItem miSetPageSizeMhdpi = new MenuItem() { Header = "_mhdpi,480*320", CommandParameter = "mhdpi", };
            MenuItem miSetPageSizeLhdpi = new MenuItem() { Header = "_lhdpi,320*240", CommandParameter = "lhdpi", };

            miSetPageSizePortableDevice.Items.Add(miSetPageSizeXxhdpi);
            miSetPageSizePortableDevice.Items.Add(miSetPageSizeXhdpi);
            miSetPageSizePortableDevice.Items.Add(miSetPageSizeHdpi);
            miSetPageSizePortableDevice.Items.Add(miSetPageSizeMhdpi);
            miSetPageSizePortableDevice.Items.Add(miSetPageSizeLhdpi);

            miSetPageSizeA3.Command =
                miSetPageSizeA4.Command =
                miSetPageSizeA5.Command =
                miSetPageSizeA6.Command =
                //miSetPageSizeSlide.Command =
                miSetPageSizeSlide640_480.Command =
                miSetPageSizeSlide800_600.Command =
                miSetPageSizeSlide1024_768.Command =
                miSetPageSizeXxhdpi.Command =
                miSetPageSizeXhdpi.Command =
                miSetPageSizeHdpi.Command =
                miSetPageSizeMhdpi.Command =
                miSetPageSizeLhdpi.Command =
                    Commands.SetPaperSizeCommand.RoutedUICmd;

            pageContextMenu.Items.Add(miSetPageSizePaper);
            pageContextMenu.Items.Add(miSetPageSizeSlide);
            pageContextMenu.Items.Add(miSetPageSizePortableDevice);

            MenuItem miSetAsDefaultPaperDirectionAndSize = new MenuItem()
            {
                Header = "设置为默认指向与尺寸(_D)",
                ToolTip = "设置为下次启动时新空白页默认形态",
            };
            miSetAsDefaultPaperDirectionAndSize.Click += MiSetAsDefaultPaperDirectionAndSize_Click;
            pageContextMenu.Items.Add(miSetAsDefaultPaperDirectionAndSize);

            pageContextMenu.Items.Add(new Separator());

            MenuItem miSetPageSideMultiple = new MenuItem() { Header = "设置页边扩展倍数(_M)" };

            MenuItem miPageSidemultipleHelp = new MenuItem() { Header = "页边扩展说明(_H)" };
            miPageSidemultipleHelp.Click += miPageSidemultipleHelp_Click;
            miSetPageSideMultiple.Items.Add(miPageSidemultipleHelp);

            miSetPageSideMultiple.Items.Add(new Separator());

            //设置页面长边扩展倍数。
            MenuItem miSetPageLongSideMultiple = new MenuItem() { InputGestureText = "长边" };
            Slider sdSetPageLongSideMultiple = new Slider()
            {
                Width = 95,
                Minimum = 1,
                Maximum = 20,
                AutoToolTipPrecision = 0,
                AutoToolTipPlacement = System.Windows.Controls.Primitives.AutoToolTipPlacement.TopLeft,
                TickFrequency = 1,
            };
            sdSetPageLongSideMultiple.ValueChanged += sdSetPageLongSideMultiple_ValueChanged;
            miSetPageLongSideMultiple.Header = sdSetPageLongSideMultiple;

            //设置页面短边扩展倍数。
            MenuItem miSetPageShortSideMultiple = new MenuItem() { InputGestureText = "短边" };
            Slider sdSetPageShortSideMultiple = new Slider()
            {
                Width = 95,
                Minimum = 1,
                Maximum = 20,
                AutoToolTipPrecision = 0,
                AutoToolTipPlacement = System.Windows.Controls.Primitives.AutoToolTipPlacement.TopLeft,
                TickFrequency = 1,
            };
            sdSetPageShortSideMultiple.ValueChanged += sdSetPageShortSideMultiple_ValueChanged;
            miSetPageShortSideMultiple.Header = sdSetPageShortSideMultiple;

            miSetPageSideMultiple.Items.Add(miSetPageLongSideMultiple);
            miSetPageSideMultiple.Items.Add(miSetPageShortSideMultiple);

            miSetPageSideMultiple.Items.Add(new Separator());

            //取消页面扩展
            MenuItem miCancelPageSideMultiple = new MenuItem() { Header = "取消页边扩展(_C)" };
            miCancelPageSideMultiple.Click += miCancelPageSideMultiple_Click;

            miSetPageSideMultiple.Items.Add(miCancelPageSideMultiple);


            pageContextMenu.Items.Add(miSetPageSideMultiple);

            pageContextMenu.Items.Add(new Separator());

            MenuItem miCopyPageToImage = new MenuItem() { Header = "复制页面图像(_I)", };
            miCopyPageToImage.Command = Commands.CopyPageToImageCommand.RoutedUICmd;

            pageContextMenu.Items.Add(miCopyPageToImage);

            MenuItem miCopyPageToXaml = new MenuItem() { Header = "将页面复制为Xaml(_X)", };
            miCopyPageToXaml.Command = Commands.CopyPageToXamlCommand.RoutedUICmd;
            PageContextMenu.Items.Add(miCopyPageToXaml);

            pageContextMenu.Items.Add(new Separator());

            MenuItem miLeftSideBackColor = new MenuItem() { Header = "左侧边色(_L)", };

            MenuItem miLeftSideBackColor_Red = new MenuItem()
            {
                Header = "红(_R)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Red,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miLeftSideBackColor_Red.Click += new RoutedEventHandler(miLeftSideBackColor_Red_Click);
            MenuItem miLeftSideBackColor_Yellow = new MenuItem()
            {
                Header = "黄(_Y)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Yellow,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miLeftSideBackColor_Yellow.Click += new RoutedEventHandler(miLeftSideBackColor_Yellow_Click);
            MenuItem miLeftSideBackColor_Blue = new MenuItem()
            {
                Header = "蓝(_B)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Blue,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miLeftSideBackColor_Blue.Click += new RoutedEventHandler(miLeftSideBackColor_Blue_Click);
            MenuItem miLeftSideBackColor_Green = new MenuItem()
            {
                Header = "绿(_G)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Green,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miLeftSideBackColor_Green.Click += new RoutedEventHandler(miLeftSideBackColor_Green_Click);

            MenuItem miLeftSideBackColor_Violet = new MenuItem()
            {
                Header = "紫(_V)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Violet,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miLeftSideBackColor_Violet.Click += new RoutedEventHandler(miLeftSideBackColor_Violet_Click);

            MenuItem miLeftSideBackColor_Transparent = new MenuItem()
            {
                Header = "透明(_T)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Transparent,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miLeftSideBackColor_Transparent.Click += new RoutedEventHandler(miLeftSideBackColor_Transparent_Click);

            miLeftSideBackColor.Items.Add(miLeftSideBackColor_Red);
            miLeftSideBackColor.Items.Add(miLeftSideBackColor_Yellow);
            miLeftSideBackColor.Items.Add(miLeftSideBackColor_Blue);
            miLeftSideBackColor.Items.Add(miLeftSideBackColor_Green);
            miLeftSideBackColor.Items.Add(miLeftSideBackColor_Violet);
            miLeftSideBackColor.Items.Add(new Separator());
            miLeftSideBackColor.Items.Add(miLeftSideBackColor_Transparent);

            MenuItem miRightSideBackColor = new MenuItem() { Header = "右侧边色(_R)", };

            MenuItem miRightSideBackColor_Red = new MenuItem()
            {
                Header = "红(_R)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Red,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miRightSideBackColor_Red.Click += new RoutedEventHandler(miRightSideBackColor_Red_Click);
            MenuItem miRightSideBackColor_Yellow = new MenuItem()
            {
                Header = "黄(_Y)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Yellow,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miRightSideBackColor_Yellow.Click += new RoutedEventHandler(miRightSideBackColor_Yellow_Click);
            MenuItem miRightSideBackColor_Blue = new MenuItem()
            {
                Header = "蓝(_B)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Blue,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miRightSideBackColor_Blue.Click += new RoutedEventHandler(miRightSideBackColor_Blue_Click);
            MenuItem miRightSideBackColor_Green = new MenuItem()
            {
                Header = "绿(_G)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Green,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miRightSideBackColor_Green.Click += new RoutedEventHandler(miRightSideBackColor_Green_Click);
            MenuItem miRightSideBackColor_Violet = new MenuItem()
            {
                Header = "紫(_V)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Violet,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miRightSideBackColor_Violet.Click += new RoutedEventHandler(miRightSideBackColor_Violet_Click);

            MenuItem miRightSideBackColor_Transparent = new MenuItem()
            {
                Header = "透明(_T)",
                Icon = new Rectangle()
                {
                    Fill = Brushes.Transparent,
                    Width = 15,
                    Height = 15,
                    StrokeThickness = 0,
                }
            };
            miRightSideBackColor_Transparent.Click += new RoutedEventHandler(miRightSideBackColor_Transparent_Click);

            miRightSideBackColor.Items.Add(miRightSideBackColor_Red);
            miRightSideBackColor.Items.Add(miRightSideBackColor_Yellow);
            miRightSideBackColor.Items.Add(miRightSideBackColor_Blue);
            miRightSideBackColor.Items.Add(miRightSideBackColor_Green);
            miRightSideBackColor.Items.Add(miRightSideBackColor_Violet);
            miRightSideBackColor.Items.Add(new Separator());
            miRightSideBackColor.Items.Add(miRightSideBackColor_Transparent);

            pageContextMenu.Items.Add(miLeftSideBackColor);
            pageContextMenu.Items.Add(miRightSideBackColor);

        }

        private static void MiSetAsDefaultPaperDirectionAndSize_Click(object sender, RoutedEventArgs e)
        {
            var activePage = Globals.MainWindow.EditorManager.GetMainSelectedPageEditor();
            if (activePage == null)
            {
                MessageBox.Show("　　请先选定一个页面再执行此操作！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            Globals.ConfigManager.Set(XmlTags.PaperSizeTag, activePage.PaperSize.PaperTypeName);

            Globals.MainWindow.EditorManager.DefPaperInfo = activePage.PaperSize;
        }

        static void miPageSidemultipleHelp_Click(object sender, RoutedEventArgs e)
        {
            LunarMessage.Warning("　　页边扩展会影响打印。一般只用于不需要打印的场合。");
        }

        static void miCancelPageSideMultiple_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageShortSideMultipleCommand.Execute(1);
            Commands.SetPageLongSideMultipleCommand.Execute(1);
        }

        static void sdSetPageShortSideMultiple_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            Commands.SetPageShortSideMultipleCommand.Execute((int)((sender as Slider).Value));
        }

        static void sdSetPageLongSideMultiple_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            Commands.SetPageLongSideMultipleCommand.Execute((int)((sender as Slider).Value));
        }

        static void miRightSideBackColor_Red_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageRightSideColorCommand.Execute(Brushes.Red);
        }

        static void miRightSideBackColor_Yellow_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageRightSideColorCommand.Execute(Brushes.Yellow);
        }

        static void miRightSideBackColor_Blue_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageRightSideColorCommand.Execute(Brushes.Blue);
        }

        static void miRightSideBackColor_Green_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageRightSideColorCommand.Execute(Brushes.Green);
        }

        static void miRightSideBackColor_Violet_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageRightSideColorCommand.Execute(Brushes.Violet);
        }

        static void miRightSideBackColor_Transparent_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageRightSideColorCommand.Execute(Brushes.Transparent);
        }

        static void miLeftSideBackColor_Red_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageLeftSideColorCommand.Execute(Brushes.Red);
        }

        static void miLeftSideBackColor_Yellow_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageLeftSideColorCommand.Execute(Brushes.Yellow);
        }

        static void miLeftSideBackColor_Blue_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageLeftSideColorCommand.Execute(Brushes.Blue);
        }

        static void miLeftSideBackColor_Green_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageLeftSideColorCommand.Execute(Brushes.Green);
        }

        static void miLeftSideBackColor_Violet_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageLeftSideColorCommand.Execute(Brushes.Violet);
        }

        static void miLeftSideBackColor_Transparent_Click(object sender, RoutedEventArgs e)
        {
            Commands.SetPageLeftSideColorCommand.Execute(Brushes.Transparent);
        }


        private Line leftAssistLine = new Line();
        private Line verticalCenterAssistLine = new Line();
        private Line rightAssistLine = new Line();
        private Line topAssistLine = new Line();
        private Line horizontalCenterAssistLine = new Line();
        private Line bottomAssistLine = new Line();

        /// <summary>
        /// PageEditor类的构造方法。
        /// </summary>
        /// <param name="masterManager">应传入编辑器的管理器。</param>
        public PageEditor(EditorManager masterManager)
        {
            if (masterManager == null) throw new ArgumentNullException("masterManager");

            this.ContextMenu = pageContextMenu;

            this.HorizontalAlignment = HorizontalAlignment.Center;
            this.VerticalAlignment = VerticalAlignment.Center;
            this.Margin = PageEditor.baseMargin;

            //注意顺序，避免再设置ZIndex。

            //添加页眉矩形
            this.baseCanvas.Children.Add(this.pageLeftSideRectangle);

            //添加页脚矩形
            this.baseCanvas.Children.Add(this.pageRightSideRectangle);

            this.baseCanvas.Children.Add(this.pageHeader);
            Canvas.SetLeft(this.pageHeader, 20);
            Canvas.SetTop(this.pageHeader, 20);

            this.baseCanvas.Children.Add(this.pageFooter);

            Binding pageHeaderTextBinding = new Binding("PageHeader");
            pageHeaderTextBinding.Source = masterManager;

            this.pageHeader.SetBinding(TextBlock.TextProperty, pageHeaderTextBinding);

            Binding pageFooterTextBinding = new Binding("PageFooter");
            pageFooterTextBinding.Source = masterManager;

            this.pageFooter.SetBinding(TextBlock.TextProperty, pageFooterTextBinding);

            this.baseCanvas.Children.Add(this.pagination);

            this.baseCanvas.Children.Add(this.tbPageTitle);

            //添加页面编辑区矩形。
            editorAdornerDecorator = new AdornerDecorator();
            this.editAreaRectangle.Stroke = this.editAreaRectangle.Fill = Brushes.Transparent;//都透明即可。
            editorAdornerDecorator.Child = this.editAreaRectangle;
            this.baseCanvas.Children.Add(editorAdornerDecorator);

            this.editAreaAdorner = new PageEditAreaGridAdorner(this.editAreaRectangle, this);
            editorAdornerDecorator.AdornerLayer.Add(this.editAreaAdorner);

            //2012年6月14日。废弃EditorManager.DefaultForeground。
            //Binding foregroundBinding = new Binding("DefaultForeground");
            //Binding foregroundBinding = new Binding("WidgetSelectionAdornerBrush");
            //foregroundBinding.Source = masterManager;
            //this.editAreaRectangle.SetBinding(Rectangle.StrokeProperty, foregroundBinding);
            RenderOptions.SetEdgeMode(editAreaRectangle, EdgeMode.Aliased);

            //统一页面辅助信息的字号
            this.pageHeader.FontSize = this.pageFooter.FontSize =
                this.pagination.FontSize = this.tbPageTitle.FontSize = 12;

            //与主窗口管理器挂接。
            this.masterManager = masterManager;
            masterManager.LinkMouseEvents(this);

            Binding backgroundBinding = new Binding(XmlTags.DocumentBackgroundTag);
            backgroundBinding.Source = this.masterManager;
            this.baseCanvas.SetBinding(Canvas.BackgroundProperty, backgroundBinding);

            #region 完成容器嵌套和尺寸绑定
            this.Child = this.baseCanvas;

            this.mainCanvas.ContextMenu = PageEditor.PageContextMenu;//挂接页面右键菜单。
            this.baseCanvas.Children.Add(this.mainCanvas);

            Binding windthBinding = new Binding("Width");
            windthBinding.Source = baseCanvas;
            mainCanvas.SetBinding(Canvas.WidthProperty, windthBinding);

            Binding heightBinding = new Binding("Height");
            heightBinding.Source = baseCanvas;
            mainCanvas.SetBinding(Canvas.HeightProperty, heightBinding);

            //this.RefreshPaperDirectionAndSize();
            #endregion

            this.insertPointAdorner = new InsertPointAdorner(this.baseCanvas, this);
            this.AdornerLayer.Add(this.insertPointAdorner);

            this.RefreshInsertPoint();

            this.selectedAdorner = new PageSelectedAdorner(this.baseCanvas, this);
            this.AdornerLayer.Add(this.selectedAdorner);

            this.addPageAdorner = new AddPageAdorner(this.BaseCanvas, this) { ToolTip = "添加页面", };
            this.AdornerLayer.Add(this.AddPageAdorner);
            this.AddPageAdorner.MouseLeftButtonDown += AddPageAdorner_MouseLeftButtonDown;

            this.copyPageAdorner = new CopyPageAdorner(this.baseCanvas, this) { ToolTip = "复制页面", };
            this.AdornerLayer.Add(this.copyPageAdorner);
            this.CopyPageAdorner.MouseLeftButtonDown += CopyPageAdorner_MouseLeftButtonDown;

            //TODO: PageEditor类构造方法的其它初始化操作。
            this.baseCanvas.PreviewMouseLeftButtonUp +=
                new MouseButtonEventHandler(baseCanvas_PreviewMouseLeftButtonUp);

            this.baseCanvas.PreviewMouseMove += new MouseEventHandler(baseCanvas_PreviewMouseMove);

            this.mainCanvas.MouseLeftButtonDown +=
                new System.Windows.Input.MouseButtonEventHandler(mainCanvas_MouseLeftButtonDown);
            this.mainCanvas.PreviewMouseRightButtonDown += new MouseButtonEventHandler(mainCanvas_PreviewMouseRightButtonDown);
            //this.mainCanvas.MouseLeftButtonUp +=
            //    new MouseButtonEventHandler(mainCanvas_MouseLeftButtonUp);

            this.baseCanvas.SizeChanged += new SizeChangedEventHandler(baseCanvas_SizeChanged);

            //注意添加的顺序。用于模拟插入线条位置的Line、模拟选定框的Rectangle都要最后添加，
            //这样才能浮在mainCanvas上面（以免去设置ZIndex）。
            this.baseCanvas.Children.Add(vEllipse);
            this.baseCanvas.Children.Add(vLine);
            this.baseCanvas.Children.Add(vPolyLine);
            this.baseCanvas.Children.Add(vRectangle);
            this.baseCanvas.Children.Add(vCopyDraggingRectangle);

            this.selectedBoxFillBrush.Visual = this.mainCanvas;
            this.selectedBoxFillBrush.ViewportUnits = BrushMappingMode.Absolute;
            //this.selectedBoxFillBrush.Viewport.Width=             //这两行由baseCanvas_SizeChanged方法处理，因为mainCanvas的尺寸总是与baseCanvas相同。
            //this.selectedBoxFillBrush.Viewport.Height=


            this.vPolyBezierLine.Data = new PathGeometry();
            (vPolyBezierLine.Data as PathGeometry).Figures.Add(vPolyBezierFigure);
            vPolyBezierFigure.Segments.Add(vPolyBezierSegment);
            this.baseCanvas.Children.Add(vPolyBezierLine);

            //格式刷事件
            this.WidgetFormated += new EventHandler<WidgetFormatedEventArgs>(PageEditor_WidgetFormated);

            //if (this.masterManager != null)
            //{
            //    this.AssistGridForm = this.masterManager.AssistGridForm;
            //}

            //六条对齐辅助线（不是版面辅助线）
            bottomAssistLine.Stroke =
            verticalCenterAssistLine.Stroke =
            topAssistLine.Stroke =
            rightAssistLine.Stroke =
            horizontalCenterAssistLine.Stroke =
                leftAssistLine.Stroke = MasterManager.WidgetEndControlerBrush;

            bottomAssistLine.StrokeThickness =
            verticalCenterAssistLine.StrokeThickness =
            topAssistLine.StrokeThickness =
            rightAssistLine.StrokeThickness =
            horizontalCenterAssistLine.StrokeThickness =
                leftAssistLine.StrokeThickness = 1;

            bottomAssistLine.StrokeDashArray =
            verticalCenterAssistLine.StrokeDashArray =
            topAssistLine.StrokeDashArray =
            rightAssistLine.StrokeDashArray =
            horizontalCenterAssistLine.StrokeDashArray =
                leftAssistLine.StrokeDashArray = new DoubleCollection() { 6, 3 };


            bottomAssistLine.Visibility =
            verticalCenterAssistLine.Visibility =
            topAssistLine.Visibility =
            rightAssistLine.Visibility =
            horizontalCenterAssistLine.Visibility =
                leftAssistLine.Visibility = System.Windows.Visibility.Collapsed;

            RenderOptions.SetEdgeMode(leftAssistLine, EdgeMode.Aliased);
            RenderOptions.SetEdgeMode(verticalCenterAssistLine, EdgeMode.Aliased);
            RenderOptions.SetEdgeMode(topAssistLine, EdgeMode.Aliased);
            RenderOptions.SetEdgeMode(rightAssistLine, EdgeMode.Aliased);
            RenderOptions.SetEdgeMode(horizontalCenterAssistLine, EdgeMode.Aliased);
            RenderOptions.SetEdgeMode(bottomAssistLine, EdgeMode.Aliased);

            this.baseCanvas.Children.Add(leftAssistLine);
            this.baseCanvas.Children.Add(verticalCenterAssistLine);
            this.baseCanvas.Children.Add(rightAssistLine);
            this.baseCanvas.Children.Add(topAssistLine);
            this.baseCanvas.Children.Add(horizontalCenterAssistLine);
            this.baseCanvas.Children.Add(bottomAssistLine);

        }

        private void CopyPageAdorner_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LunarMessage.Warning(Commands.InsertPageCopyEditorCommand.Execute());
        }

        private void AddPageAdorner_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LunarMessage.Warning(Commands.InsertNewPageEditorCommand.Execute());
        }

        #endregion

        #region 字段与属性===================================================================================================

        private string commentText = string.Empty;
        /// <summary>
        /// [读写]页面备注文本。
        /// </summary>
        public string CommentText
        {
            get { return this.commentText; }
            set
            {
                this.commentText = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.CommentTextTag, XmlTools.ReplaceXmlChars(value));
                }
            }
        }

        private static ContextMenu pageContextMenu;
        /// <summary>
        /// 页面快捷菜单。
        /// </summary>
        public static ContextMenu PageContextMenu
        {
            get { return PageEditor.pageContextMenu; }
        }

        /// <summary>
        /// 最外层的Canvas，里面会有些部件浮动在内部mainCanvas的表层，用于进行一些操作。（例如：几个控制点）
        /// </summary>
        private Canvas baseCanvas = new Canvas() { ClipToBounds = true };
        /// <summary>
        /// [只读]基面板。导出图像时要用到。
        /// </summary>
        public Canvas BaseCanvas
        {
            get { return baseCanvas; }
        }

        /// <summary>
        /// [静态字段]表示页面外部基本的空缺。
        /// </summary>
        private static Thickness baseMargin = new Thickness(20);

        private Point baseInsertPoint = new Point(61, 50);
        /// <summary>
        /// 表示当前“插入点位置”。新普通部件将插入到此位置。线型部件则与此无关。
        /// </summary>
        public Point BaseInsertPoint
        {
            get { return baseInsertPoint; }
            set
            {
                baseInsertPoint = value;
                this.RefreshInsertPoint();
            }
        }

        /// <summary>
        /// [只读]返回边框的四边宽度。
        /// </summary>
        public Thickness BorderThickness
        {
            get { return new Thickness(0); }
        }

        /// <summary>
        /// [只读]公开mainCanvas的Children。
        /// </summary>
        public UIElementCollection Children
        {
            get
            {
                return this.mainCanvas.Children;
            }
        }

        private Rect editArea = new Rect();
        /// <summary>
        /// [只读]编辑区尺寸。
        /// </summary>
        public Rect EditArea
        {
            get { return editArea; }
        }

        /// <summary>
        /// 用于显示网格线的装饰器。使用DrawingBrush解决不了模糊问题。
        /// </summary>
        private PageEditAreaGridAdorner editAreaAdorner;

        /// <summary>
        /// 覆盖在EditAreaRectangle外的装饰层。用以填充网格图形装饰器。
        /// </summary>
        private AdornerDecorator editorAdornerDecorator;

        /// <summary>
        /// 表示编辑区的边界线。
        /// </summary>
        private Rectangle editAreaRectangle = new Rectangle()
        {
            Fill = null,
            StrokeThickness = 1,
            SnapsToDevicePixels = true,
            StrokeDashArray = LineDashType.dotCollection,
            Opacity = 0.8,
        };

        private string id;
        /// <summary>
        /// [只读]每个编辑器都有的唯一标识符。
        /// </summary>
        public string Id
        {
            get { return id; }
        }


        private AssistGridForm assistGridForm = AssistGridForm.Box;

        /// <summary>
        /// [读写]是否显示风格线。默认只显示为Box。不随文档保存。
        /// </summary>
        public AssistGridForm AssistGridForm
        {
            get { return assistGridForm; }
            set
            {
                assistGridForm = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.AssistGridFormTag, assistGridForm.ToString());
                }
                RefreshAssistGridForm();
            }
        }

        public void RefreshAssistGridForm()
        {
            this.editAreaAdorner.InvalidateVisual();
            if (this.editAreaAdorner.Visibility != Visibility.Visible)
                this.editAreaAdorner.Visibility = Visibility.Visible;
        }

        public void HideAssistGridForm()
        {
            if (this.editAreaAdorner.Visibility != Visibility.Hidden)
                this.editAreaAdorner.Visibility = Visibility.Hidden;
        }

        /// <summary>
        /// 向用户标示“当前插入点位置”的装饰器。
        /// </summary>
        private Adorners.InsertPointAdorner insertPointAdorner;

        private bool isMainSelected = false;
        /// <summary>
        /// 表示当前页是否是“活动页”。
        /// 此属性具有排他性。
        /// 此一属性值与IsSelected属性相互影响。
        /// </summary>
        public bool IsMainSelected
        {
            get { return isMainSelected; }
            set
            {
                isMainSelected = value;

                this.RefreshIsSelected();

                if (isMainSelected == false)
                {
                    this.mouseInfo.DraggingType = Enums.PageDraggingType.SelectWidgets;

                    if (this.masterManager != null)
                    {
                        this.masterManager.PreviewMainSelectedPageEditor = this;
                    }
                }
                else
                {
                    if (this.masterManager != null)
                    {
                        this.masterManager.OnMainSelectedPageChanged(this, new MainSelectedPageEditorChangedEventArgs()
                        {
                            PageEditor = this,
                        });
                    }
                }
            }
        }

        private bool isSelected = false;
        /// <summary>
        /// 表示当前页编辑器是否处于“被选定”状态。
        /// </summary>
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                isSelected = value;
                if (value == false)
                {
                    if (IsMainSelected)
                    {
                        isMainSelected = false;
                        if (masterManager != null)
                        {
                            masterManager.PreviewMainSelectedPageEditor = this;
                        }
                    }
                }

                this.RefreshIsSelected();
            }
        }

        /// <summary>
        /// 用以承载部件的主Canvas。
        /// </summary>
        private Canvas mainCanvas = new Canvas()
        {
            Background = Brushes.Transparent,
        };

        /// <summary>
        /// [只写]只用于触发MainSelectedWidgetChanged事件。
        /// </summary>
        public Widget MainSelectedWidget
        {
            set { OnMainSelectedWidgetChanged(this, new MainSelectedWidgetChangedEventArgs(value)); }
        }

        private EditorManager masterManager;
        /// <summary>
        /// [只读]返回此编辑器所属的封装编辑器（EditorManager）。
        /// </summary>
        public EditorManager MasterManager
        {
            get { return masterManager; }
        }

        /// <summary>
        /// [只读]返回MasterWindow的主窗口。
        /// 如果MasterManager为null或MasterManager的MasterWindow为null，返回null。
        /// </summary>
        public MainWindow MasterWindow
        {
            get
            {
                if (masterManager == null) return null;

                return masterManager.MasterWindow;
            }
        }

        /// <summary>
        /// [只读]主要部件承载区。
        /// </summary>
        public Canvas MainCanvas
        {
            get
            {
                return this.mainCanvas;
            }
        }

        private MousePointInfo mouseInfo = new MousePointInfo();
        /// <summary>
        /// 鼠标指针位置。
        /// </summary>
        public MousePointInfo MouseInfo
        {
            get
            {
                return this.mouseInfo;
            }
            set
            {
                this.mouseInfo = value;
            }
        }

        public MoonPdfLib.MoonPdfPanel PdfPanel { get; set; } = null;

        public Image BackgroundImage { get; set; } = null;

        public string PdfFilePath { get; set; } = null;

        public string ImageFilePath { get; set; } = null;  // 还是加上吧，但不是背景色的形式出现。只是作为临时对象。

        //不应让Page设置自己的背景色，否则需要针对各页面单独设置选取框色、部件默认配色等等——太可怕了。
        //private Brush pageBackground = Brushes.White;
        ///// <summary>
        ///// [只读]表示页面的背景色。
        ///// </summary>
        //public Brush PageBackground
        //{
        //    get { return pageBackground; }
        //    set
        //    {
        //        pageBackground = value;
        //        if (this.xmlData != null)
        //        {
        //            this.xmlData.SetAttribute(XmlTags.PageBackground,
        //                BrushManager.GetEnglishName(pageBackground));
        //            RefreshPageBackground();
        //        }
        //    }
        //}

        private TextBlock pageFooter = new TextBlock()
        {
            Foreground = Brushes.DarkBlue,
        };

        /// <summary>
        /// [只读]页脚文本。
        /// </summary>
        public TextBlock PageFooter
        {
            get { return pageFooter; }
        }

        private TextBlock pageHeader = new TextBlock()
        {
            Foreground = Brushes.DarkRed,
        };

        private Rectangle pageLeftSideRectangle = new Rectangle()
        {
            Stroke = Brushes.Transparent,
            Fill = Brushes.Transparent,
            StrokeThickness = 0,
        };

        private Rectangle pageRightSideRectangle = new Rectangle()
        {
            Stroke = Brushes.Transparent,
            Fill = Brushes.Transparent,
            StrokeThickness = 0,
        };

        private Brush pageRightSideBackColor = Brushes.Transparent;
        /// <summary>
        /// [读写]整个页脚（而不是仅页脚文本所在区域）的背景色。
        /// </summary>
        public Brush PageRightSideBackColor
        {
            get { return pageRightSideBackColor; }
            set
            {
                pageRightSideBackColor = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.PageRightSideBackColorTag, Tools.BrushManager.GetName(value));
                }

                this.pageRightSideRectangle.Fill = value;
            }
        }

        private Brush pageLeftSideBackColor = Brushes.Transparent;
        /// <summary>
        /// [读写]整个页眉（而不是仅页眉文本所在区域）的背景色。
        /// </summary>
        public Brush PageLeftSideBackColor
        {
            get { return pageLeftSideBackColor; }
            set
            {
                pageLeftSideBackColor = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.PageLeftSideBackColorTag, Tools.BrushManager.GetName(value));
                }

                this.pageLeftSideRectangle.Fill = value;
            }
        }

        /// <summary>
        /// [只读]页眉文本。
        /// </summary>
        public TextBlock PageHeader
        {
            get { return pageHeader; }
        }

        private TextBlock tbPageTitle = new TextBlock()
        {
            Foreground = Brushes.DarkGray,
        };

        /// <summary>
        /// [读写]返回页标题文本块的文本。
        /// </summary>
        public String PageTitle
        {
            get { return tbPageTitle.Text; }
            set
            {
                if (value == null)
                {
                    tbPageTitle.Text = string.Empty;
                    if (this.xmlData != null)
                    {
                        this.xmlData.SetAttribute(XmlTags.PageTitleTag, string.Empty);
                    }
                }
                else
                {
                    tbPageTitle.Text = value;
                    if (this.xmlData != null)
                    {
                        this.xmlData.SetAttribute(XmlTags.PageTitleTag, value);
                    }
                }

                RefreshPageTitleLocation();
            }
        }

        private TextBlock pagination = new TextBlock()
        {
            Foreground = Brushes.DarkSlateBlue,
        };
        /// <summary>
        /// [只读]显示页码号的文本块。
        /// </summary>
        public TextBlock Pagination
        {
            get { return pagination; }
        }

        private PaperInfo paperSize = PaperInfo.GetPaperInfo("A4");
        /// <summary>
        /// 纸张尺寸。
        /// ——按支持的纸型名称来获取（支持的纸型包括：A0~A10,B0~B10）。
        /// <example>PaperInfo pi = PaperInfo.GetPaperInfo("A4");</example>
        /// </summary>
        public PaperInfo PaperSize
        {
            get { return paperSize; }
            set
            {
                paperSize = value;

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.PaperSizeTag,
                        paperSize.PaperTypeName);
                }

                RefreshPaperDirectionAndSize();
            }
        }

        private int pageLongSideMultiple = 1;
        /// <summary>
        /// [读写]页面长边扩展倍数。最终呈现的页面长边尺寸由PageSize中指定的纸型的长边乘以此值决定。默认值为1。
        /// </summary>
        public int PageLongSideMultiple
        {
            get { return this.pageLongSideMultiple; }
            set
            {
                this.pageLongSideMultiple = value;

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.PageLongSideMultipleTag,
                        this.pageLongSideMultiple.ToString());
                }

                RefreshPaperDirectionAndSize();
            }
        }

        private int pageShortSideMultiple = 1;
        /// <summary>
        /// [读写]页面短边扩展倍数。最终呈现的页面短边尺寸由PageSize中指定的纸型的短边乘以此值决定。默认值为1。
        /// </summary>
        public int PageShortSideMultiple
        {
            get { return this.pageShortSideMultiple; }
            set
            {
                this.pageShortSideMultiple = value;

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.PageShortSideMultipleTag,
                        this.pageShortSideMultiple.ToString());
                }

                RefreshPaperDirectionAndSize();
            }
        }

        private Orientation paperDirection = Orientation.Vertical;
        /// <summary>
        /// 页面的方向。
        /// </summary>
        public Orientation PaperDirection
        {
            get
            {
                return paperDirection;
            }

            set
            {
                paperDirection = value;

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.PaperDirectionTag,
                        paperDirection.ToString());
                }

                RefreshPaperDirectionAndSize();
            }
        }

        private Adorners.AddPageAdorner addPageAdorner;
        /// <summary>
        /// [只读]用于添加页面的装饰器按钮。
        /// </summary>
        public Adorners.AddPageAdorner AddPageAdorner
        {
            get { return addPageAdorner; }
        }

        private Adorners.CopyPageAdorner copyPageAdorner;
        /// <summary>
        /// [只读]用于快速复制页面的装饰器按钮。
        /// </summary>
        public Adorners.CopyPageAdorner CopyPageAdorner
        {
            get { return this.copyPageAdorner; }
        }

        /// <summary>
        /// 页面选定框。
        /// </summary>
        private Adorners.PageSelectedAdorner selectedAdorner;
        /// <summary>
        /// [只读]页面选定框装饰器。
        /// </summary>
        public Adorners.PageSelectedAdorner SelectedAdorner
        {
            get { return selectedAdorner; }
        }

        private static SolidColorBrush selectedBorderColor;
        /// <summary>
        /// [静态只读]活动边框的色彩。在静态构造方法中初始化。
        /// </summary>
        public static SolidColorBrush SelectedBorderColor
        {
            get { return PageEditor.selectedBorderColor; }
        }

        /// <summary>
        /// 用于填充选取框，这样就可以添加复制“选字区域为图像”功能了。2013年4月9日
        /// </summary>
        private VisualBrush selectedBoxFillBrush = new VisualBrush();

        /// <summary>
        /// 拖动复制时，模拟被拖动的部件。
        /// </summary>
        private Rectangle vCopyDraggingRectangle = new Rectangle()
        {
            Visibility = Visibility.Hidden,
            Stroke = Brushes.Black,
            StrokeThickness = 1,
            Fill = Brushes.Gray,
            Opacity = 0.5,
        };

        /// <summary>
        /// 用于模拟圆插入位置的虚圆（浮在mainCanvas上面）
        /// ——不用装饰器来实现，是因为装饰器重绘时闪烁。
        /// </summary>
        private Ellipse vEllipse = new Ellipse()
        {
            Visibility = Visibility.Hidden,
            Stroke = Brushes.LightBlue,
            StrokeThickness = 2,
            Opacity = 0.7,
        };

        /// <summary>
        /// 用于模拟直线和贝塞尔曲线插入位置的虚线（浮在mainCanvas上面）
        /// ——不用装饰器来实现，是因为装饰器重绘时闪烁。
        /// </summary>
        private Line vLine = new Line()
        {
            Visibility = Visibility.Hidden,
            Stroke = Brushes.LightBlue,
            StrokeThickness = 2,
            Opacity = 0.7,
        };

        private Path vPolyBezierLine = new Path()
        {
            Visibility = Visibility.Hidden,
            Stroke = Brushes.LightBlue,
            StrokeThickness = 2,
            StrokeLineJoin = PenLineJoin.Round,
            StrokeStartLineCap = PenLineCap.Round,
            StrokeEndLineCap = PenLineCap.Round,
            Opacity = 0.7,
        };

        private PathFigure vPolyBezierFigure = new PathFigure() { IsClosed = false };

        private PolyBezierSegment vPolyBezierSegment = new PolyBezierSegment();

        /// <summary>
        /// 用于模拟折线插入位置的虚线（浮在mainCanvas上面）
        /// ——不用装饰器来实现，是因为装饰器重绘时闪烁。
        /// </summary>
        private Polyline vPolyLine = new Polyline()
        {
            Visibility = Visibility.Hidden,
            Stroke = Brushes.LightBlue,
            StrokeThickness = 2,
            Opacity = 0.7,
        };

        /// <summary>
        /// 用于模拟选定框的虚框（浮在mainCanvas上面），框选结束时，涉及到的部件都被选定。
        /// ——不用装饰器来实现，是因为装饰器重绘时闪烁。
        /// </summary>
        private Rectangle vRectangle = new Rectangle()
        {
            Visibility = Visibility.Hidden,
            Stroke = Brushes.DarkCyan,
            StrokeThickness = 2,
            Fill = Brushes.LightBlue,
            Opacity = 0.7,
        };

        /// <summary>
        /// [只读]取当前页面节点的“WidgetSet”子节点。意外情况下可能返回null。一般不应出现此情况。
        /// </summary>
        public XmlNode WidgetSetNode
        {
            get
            {
                if (this.xmlData == null) return null;

                XmlNode widgetSetNode = this.xmlData.SelectSingleNode(XmlTags.WidgetSetTag);
                if (widgetSetNode == null)
                {
                    widgetSetNode = this.xmlData.AppendXmlAsChild("<" + XmlTags.WidgetSetTag + " />");
                }

                return widgetSetNode;
            }
        }

        private XmlNode xmlData;

        /// <summary>
        /// 用以生成当前编辑器中所有内容的Xml数据节点。
        /// </summary>
        public XmlNode XmlData
        {
            get { return xmlData; }
            set
            {
                xmlData = value;
                this.Build();
            }
        }

        #endregion

        #region 方法=========================================================================================================

        /// <summary>
        /// 将Widget添加到mainCanvas中。
        /// </summary>
        /// <param name="sw">要添加的Widget。</param>
        /// <returns></returns>
        public int AddWidget(Widgets.Widget w)
        {
            if (w == null) return -1;

            int result = this.mainCanvas.Children.Add(w);

            w.RefreshLocation();//防止“组”的尺寸有问题。

            return result;
        }

        /// <summary>
        /// 完成：①选定部件（会取消其它不相干部件的选定状态）；
        ///         ——移动插入点由mainCanvas.MouseLeftButtonUp实现；
        ///       ②或者完成部件拖动后的停放；
        ///       ③或者完成部件控制点拖动后的停放；
        ///       ④或者插入线型部件。
        /// </summary>
        void baseCanvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            HideAssistLines();

            KeyStates ksLeftCtrl = Keyboard.GetKeyStates(Key.LeftCtrl);
            KeyStates ksRightCtrl = Keyboard.GetKeyStates(Key.RightCtrl);
            KeyStates ksLeftShift = Keyboard.GetKeyStates(Key.LeftShift);
            KeyStates ksRightShift = Keyboard.GetKeyStates(Key.RightShift);
            KeyStates ksLeftAlt = Keyboard.GetKeyStates(Key.LeftAlt);
            KeyStates ksRightAlt = Keyboard.GetKeyStates(Key.RightAlt);
            KeyStates ksLeftWin = Keyboard.GetKeyStates(Key.LWin);
            KeyStates ksRightWin = Keyboard.GetKeyStates(Key.RWin);

            bool isCtrl = ((ksLeftCtrl & KeyStates.Down) > 0 || (ksRightCtrl & KeyStates.Down) > 0);
            bool isShift = ((ksLeftShift & KeyStates.Down) > 0 || (ksRightShift & KeyStates.Down) > 0);
            bool isAlt = ((ksLeftAlt & KeyStates.Down) > 0 || (ksRightAlt & KeyStates.Down) > 0);
            bool isWin = ((ksLeftWin & KeyStates.Down) > 0 || (ksRightWin & KeyStates.Down) > 0);

            ModifierKeys modifierKeys = ModifierKeys.None;
            if (isCtrl) { modifierKeys |= ModifierKeys.Control; }
            if (isShift) { modifierKeys |= ModifierKeys.Shift; }
            if (isAlt) { modifierKeys |= ModifierKeys.Alt; }
            if (isWin) { modifierKeys |= ModifierKeys.Windows; }

            vLine.Visibility = Visibility.Hidden;
            vEllipse.Visibility = Visibility.Hidden;
            vRectangle.Visibility = Visibility.Hidden;
            vPolyLine.Visibility = Visibility.Hidden;
            vPolyBezierLine.Visibility = Visibility.Hidden;
            vCopyDraggingRectangle.Visibility = Visibility.Hidden;

            Point startPoint = mouseInfo.LeftButtonPreviewPoint;
            Point realCurPoint = e.GetPosition(this.baseCanvas);
            Point relativeLinePoint = GetFormatedLineMovingPoint(startPoint, realCurPoint);
            Point relativeShapePoint = GetFormatedShapeMovingPoint(startPoint, realCurPoint);
            Point curPoint;

            //与普通操作不同：跳到指定页面需要精确定位。
            if (Math.Abs(realCurPoint.X - startPoint.X) < 1 && Math.Abs(realCurPoint.Y - startPoint.Y) < 1
               && this.mouseInfo.DraggingType != Enums.PageDraggingType.JumpToLinkedPageEditor)
            {
                if (this.mouseInfo.DraggingType == Enums.PageDraggingType.MoveWidgets)
                {
                    if (this.masterManager != null)
                    {
                        this.mouseInfo.DraggingType = this.masterManager.MouseDraggingType;
                    }
                    else
                    {
                        this.mouseInfo.DraggingType = Enums.PageDraggingType.None;
                    }

                    foreach (UIElement ue in this.mainCanvas.Children)
                    {
                        Widget w = ue as Widget;
                        if (w != null) w.RefreshLocation();
                    }
                    return;//位置太近，不视为拖动。
                }

                //不触发MouseLeftButtonDropped事件，只是移动插入点。
                this.BaseInsertPoint = realCurPoint;
                //移动插入点，说明没有点击任何部件（除非使用命令来移动插入点）
                this.MainSelectedWidget = null;//取消所有部件的选定。

                if (this.masterManager != null)
                {
                    this.mouseInfo.DraggingType = this.masterManager.MouseDraggingType;
                }
                else
                {
                    this.mouseInfo.DraggingType = Enums.PageDraggingType.None;
                }

                masterManager.ClearWidgetsSelection();
                return;
            }

            switch (this.mouseInfo.DraggingType)
            {
                case Enums.PageDraggingType.InsertBezierLine:
                case Enums.PageDraggingType.InsertStraitLine:
                case Enums.PageDraggingType.InsertBezierLineRelation:
                case Enums.PageDraggingType.InsertPolyLineRelation:
                case Enums.PageDraggingType.InsertStraitLineRelation:
                    {
                        if (Globals.MainWindow.IsPresentatingByPath) return;

                        curPoint = mouseInfo.LeftButtonPoint = (isShift ? relativeLinePoint : realCurPoint);

                        MouseLeftButtonDraggingEventArgs eArgs = new MouseLeftButtonDraggingEventArgs()
                        {
                            MasterPageEditor = this,
                            DraggingType = this.mouseInfo.DraggingType,
                            MainSelectedWidget = this.mouseInfo.MainSelectedWidget,
                            Modifiers = modifierKeys,
                        };

                        //用于添加部件时，只需要两个点的坐标即可。
                        eArgs.StartPoint = startPoint;
                        eArgs.EndPoint = curPoint;

                        OnMouseLeftButtonDropped(this, eArgs);
                        break;
                    }
                case Enums.PageDraggingType.InsertBracket:
                case Enums.PageDraggingType.InsertEllipse:
                case Enums.PageDraggingType.InsertPolyLine:
                case Enums.PageDraggingType.InsertRectangle:
                case Enums.PageDraggingType.InsertRhomb:
                case Enums.PageDraggingType.InsertTriangle:
                    {
                        if (Globals.MainWindow.IsPresentatingByPath) return;

                        curPoint = mouseInfo.LeftButtonPoint = (isShift ? relativeShapePoint : realCurPoint);

                        MouseLeftButtonDraggingEventArgs eArgs = new MouseLeftButtonDraggingEventArgs()
                        {
                            MasterPageEditor = this,
                            DraggingType = this.mouseInfo.DraggingType,
                            MainSelectedWidget = this.mouseInfo.MainSelectedWidget,
                            Modifiers = modifierKeys,
                        };

                        //用于添加部件时，只需要两个点的坐标即可。
                        eArgs.StartPoint = startPoint;
                        eArgs.EndPoint = curPoint;

                        OnMouseLeftButtonDropped(this, eArgs);
                        break;
                    }
                case Enums.PageDraggingType.MoveLineWidgetControler:
                    {
                        if (Globals.MainWindow.IsPresentatingByPath) return;

                        curPoint = mouseInfo.LeftButtonPoint = (isShift ? relativeLinePoint : realCurPoint);

                        MouseLeftButtonDraggingEventArgs eArgs = new MouseLeftButtonDraggingEventArgs()
                        {
                            MasterPageEditor = this,
                            DraggingType = this.mouseInfo.DraggingType,
                            StartPoint = startPoint,
                            EndPoint = curPoint,
                            Modifiers = modifierKeys,
                        };

                        eArgs.MainSelectedWidget = this.GetMainSelectedWidget();

                        OnWidgetControlerMoved(this, eArgs);
                        break;
                    }
                case Enums.PageDraggingType.SelectWidgets:
                    {
                        curPoint = mouseInfo.LeftButtonPoint = (isShift ? relativeShapePoint : realCurPoint);

                        //选定部件。
                        SelectWidgetsInBox(curPoint, isShift || isCtrl);
                        break;
                    }
                case Enums.PageDraggingType.MoveWidgets://放置正在被拖动的部件。
                    {
                        if (Globals.MainWindow.IsPresentatingByPath) return;

                        curPoint = mouseInfo.LeftButtonPoint = (isShift ? relativeLinePoint : realCurPoint);

                        MouseLeftButtonDraggingEventArgs eArgs = new MouseLeftButtonDraggingEventArgs()
                        {
                            MasterPageEditor = this,
                            DraggingType = this.mouseInfo.DraggingType,
                            StartPoint = startPoint,
                            EndPoint = curPoint,
                            Modifiers = modifierKeys,
                        };

                        OnWidgetsMoved(this, eArgs);

                        //e.Handled = true;//会导致主界面按钮状态无法同步刷新。
                        break;
                    }
                case Enums.PageDraggingType.JumpToLinkedPageEditor:
                    {
                        return;//这个要跳过最后的“复位拖动方式”，不然无法跳转到指定页面。
                    }
            }

            if (masterManager != null)
            {
                mouseInfo.DraggingType = masterManager.MouseDraggingType;
            }
            else
            {
                mouseInfo.DraggingType = Enums.PageDraggingType.None;
            }

        }

        /// <summary>
        /// 实现：①拖动部件；
        ///       ②或拖动部件控制点；
        ///       ③或绘制模拟插入线型部件的位置（画虚线或虚框）；
        ///       ④或绘制模拟的部件选定框。
        /// </summary>
        void baseCanvas_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (this.masterManager == null || Globals.MainWindow.IsPresentatingByPath) return;

            if (e.LeftButton != MouseButtonState.Pressed) return;

            Point startPoint = mouseInfo.LeftButtonPreviewPoint;
            Point realCurPoint = e.GetPosition(this.baseCanvas);

            //注意：移动已存在的直线部件的控制点时，不能使用下面这行的结果。
            //　　　因为这行不是取直线另一点的坐标，而是取上一次鼠标点击的坐标。
            Point relativeLinePoint = GetFormatedLineMovingPoint(startPoint, realCurPoint);

            Point relativeShapePoint = GetFormatedShapeMovingPoint(startPoint, realCurPoint);
            Point curPoint;

            bool isShift = false;
            KeyStates ksLeftShift = Keyboard.GetKeyStates(Key.LeftShift);
            KeyStates ksRightShift = Keyboard.GetKeyStates(Key.RightShift);
            isShift = ((ksLeftShift & KeyStates.Down) > 0 || (ksRightShift & KeyStates.Down) > 0);

            //if (isShift)
            //{
            //    Point realCurPoint = e.GetPosition(this.baseCanvas);
            //    curPoint = GetFormatedMovingPoint(startPoint, realCurPoint);
            //}
            //else
            //{
            //    curPoint = e.GetPosition(this.baseCanvas);
            //}

            switch (mouseInfo.DraggingType)
            {
                case Enums.PageDraggingType.InsertBracket:
                    {
                        curPoint = isShift ? relativeShapePoint : realCurPoint;
                        DrawVirtualBracket(ref startPoint, ref curPoint);
                        break;
                    }
                case Enums.PageDraggingType.InsertBezierLine://刚刚添加时，曲线看起来就象是直线。
                case Enums.PageDraggingType.InsertBezierLineRelation:
                    {
                        vLine.Stroke = this.masterManager.BezierLineStyle.WidgetForeColor;
                        vLine.Fill = this.masterManager.BezierLineStyle.WidgetBackColor;
                        vLine.StrokeThickness = this.masterManager.BezierLineStyle.WidgetLineWidth;

                        curPoint = isShift ? relativeLinePoint : realCurPoint;
                        if (vLine.Visibility != Visibility.Visible) { vLine.Visibility = Visibility.Visible; }
                        vLine.X1 = startPoint.X; vLine.Y1 = startPoint.Y;
                        vLine.X2 = curPoint.X; vLine.Y2 = curPoint.Y;
                        break;
                    }
                case Enums.PageDraggingType.InsertStraitLine:
                case Enums.PageDraggingType.InsertStraitLineRelation:
                    {
                        vLine.Stroke = this.masterManager.StraitLineStyle.WidgetForeColor;
                        vLine.Fill = this.masterManager.StraitLineStyle.WidgetBackColor;
                        vLine.StrokeThickness = this.masterManager.StraitLineStyle.WidgetLineWidth;

                        curPoint = isShift ? relativeLinePoint : realCurPoint;
                        if (vLine.Visibility != Visibility.Visible) { vLine.Visibility = Visibility.Visible; }
                        vLine.X1 = startPoint.X; vLine.Y1 = startPoint.Y;
                        vLine.X2 = curPoint.X; vLine.Y2 = curPoint.Y;
                        break;
                    }
                case Enums.PageDraggingType.InsertPolyLine:
                case Enums.PageDraggingType.InsertPolyLineRelation:
                    {
                        vPolyLine.Stroke = this.masterManager.PolyLineStyle.WidgetForeColor;
                        vPolyLine.Fill = Brushes.Transparent;//this.masterManager.PolyLineStyle.WidgetBackColor;
                        vPolyLine.StrokeThickness = this.masterManager.PolyLineStyle.WidgetLineWidth;

                        curPoint = isShift ? relativeShapePoint : realCurPoint;
                        curPoint = realCurPoint;
                        if (vPolyLine.Visibility != Visibility.Visible) { vPolyLine.Visibility = Visibility.Visible; }

                        Point baseStart, baseEnd;

                        if (Math.Abs(startPoint.X - curPoint.X) > Math.Abs(startPoint.Y - curPoint.Y))
                        {
                            //横向
                            baseStart = new Point(startPoint.X, startPoint.Y + (curPoint.Y - startPoint.Y) / 2);
                            baseEnd = new Point(curPoint.X, baseStart.Y);
                        }
                        else
                        {
                            baseStart = new Point(startPoint.X + (curPoint.X - startPoint.X) / 2, startPoint.Y);
                            baseEnd = new Point(baseStart.X, curPoint.Y);
                        }

                        vPolyLine.Points = new System.Windows.Media.PointCollection() {
                        startPoint,baseStart,baseEnd,curPoint,};
                        break;
                    }
                case Enums.PageDraggingType.InsertRhomb:
                    {
                        vPolyLine.Stroke = this.masterManager.RhombStyle.WidgetLineColor;
                        vPolyLine.Fill = this.masterManager.RhombStyle.WidgetBackColor;
                        vPolyLine.StrokeThickness = this.masterManager.RhombStyle.WidgetLineWidth;

                        curPoint = isShift ? relativeShapePoint : realCurPoint;
                        if (vPolyLine.Visibility != Visibility.Visible) { vPolyLine.Visibility = Visibility.Visible; }

                        Point p1, p2, p3, p4;

                        WidgetStyle defRhombStyle;
                        var defWidgetForm = WidgetForm.Rhomb;
                        if (masterManager.FormatBrush != null)
                        {
                            // 用户样式优先。
                            defRhombStyle = masterManager.FormatBrush.DefaultWidgetStyle;
                            if (defRhombStyle.WidgetForm != WidgetForm.UnKnown)
                            {
                                defWidgetForm = defRhombStyle.WidgetForm;
                                vPolyLine.Opacity = defRhombStyle.WidgetOpacity;
                                vPolyLine.Fill = defRhombStyle.WidgetBackColor;
                                //vPolyLine.Width = defRhombStyle.WidgetLineWidth;
                                vPolyLine.Stroke = defRhombStyle.WidgetLineColor;
                            }
                        }
                        else
                        {
                            defRhombStyle = masterManager.GetDefaultWidgetStyle(typeof(RhombWidget).Name);
                            if (defRhombStyle != null)
                            {
                                defWidgetForm = defRhombStyle.WidgetForm;
                                vPolyLine.Opacity = defRhombStyle.WidgetOpacity;
                                vPolyLine.Fill = defRhombStyle.WidgetBackColor;
                                //vPolyLine.Width = defRhombStyle.WidgetLineWidth;
                                vPolyLine.Stroke = defRhombStyle.WidgetLineColor;
                            }
                        }

                        if (defWidgetForm == WidgetForm.Rectangle)
                        {
                            p1 = new Point(startPoint.X, startPoint.Y);
                            p2 = new Point(startPoint.X, curPoint.Y);
                            p3 = new Point(curPoint.X, curPoint.Y);
                            p4 = new Point(curPoint.X, startPoint.Y);
                        }
                        else
                        {
                            p1 = new Point(startPoint.X, startPoint.Y + (curPoint.Y - startPoint.Y) / 2);
                            p2 = new Point(startPoint.X + (curPoint.X - startPoint.X) / 2, startPoint.Y);
                            p3 = new Point(curPoint.X, p1.Y);
                            p4 = new Point(p2.X, curPoint.Y);
                        }

                        vPolyLine.Points = new System.Windows.Media.PointCollection() {
                        p1,p2,p3,p4,p1,};
                        break;
                    }
                case Enums.PageDraggingType.InsertTriangle:
                    {
                        vPolyLine.Stroke = this.masterManager.TriangleStyle.WidgetLineColor;
                        vPolyLine.Fill = this.masterManager.TriangleStyle.WidgetBackColor;
                        vPolyLine.StrokeThickness = this.masterManager.TriangleStyle.WidgetLineWidth;

                        curPoint = isShift ? relativeShapePoint : realCurPoint;
                        if (vPolyLine.Visibility != Visibility.Visible) { vPolyLine.Visibility = Visibility.Visible; }

                        Point p1, p2, p3;

                        p1 = startPoint; p2 = new Point(startPoint.X, curPoint.Y); p3 = curPoint;

                        vPolyLine.Points = new PointCollection() { p1, p2, p3, p1 };
                        break;
                    }
                case Enums.PageDraggingType.InsertEllipse:
                    {
                        vEllipse.Stroke = this.masterManager.EllipseStyle.WidgetLineColor;
                        vEllipse.Fill = this.masterManager.EllipseStyle.WidgetBackColor;
                        vEllipse.StrokeThickness = this.masterManager.EllipseStyle.WidgetLineWidth;

                        curPoint = isShift ? relativeShapePoint : realCurPoint;
                        if (vEllipse.Visibility != Visibility.Visible) { vEllipse.Visibility = Visibility.Visible; }

                        Rect newRect = new Rect(Math.Min(curPoint.X, mouseInfo.LeftButtonPreviewPoint.X),
                            Math.Min(curPoint.Y, mouseInfo.LeftButtonPreviewPoint.Y),
                            Math.Abs(curPoint.X - mouseInfo.LeftButtonPreviewPoint.X),
                            Math.Abs(curPoint.Y - mouseInfo.LeftButtonPreviewPoint.Y));

                        Canvas.SetLeft(vEllipse, newRect.Left);
                        Canvas.SetTop(vEllipse, newRect.Top);
                        vEllipse.Width = newRect.Width;
                        vEllipse.Height = newRect.Height;
                        break;
                    }
                case Enums.PageDraggingType.InsertRectangle:
                    {
                        vRectangle.Stroke = this.masterManager.RectangleStyle.WidgetLineColor;
                        vRectangle.Fill = this.masterManager.RectangleStyle.WidgetBackColor;
                        vRectangle.StrokeThickness = this.masterManager.RectangleStyle.WidgetLineWidth;

                        curPoint = isShift ? relativeShapePoint : realCurPoint;
                        if (vRectangle.Visibility != Visibility.Visible) { vRectangle.Visibility = Visibility.Visible; }

                        Rect newRect = new Rect(Math.Min(curPoint.X, mouseInfo.LeftButtonPreviewPoint.X),
                            Math.Min(curPoint.Y, mouseInfo.LeftButtonPreviewPoint.Y),
                            Math.Abs(curPoint.X - mouseInfo.LeftButtonPreviewPoint.X),
                            Math.Abs(curPoint.Y - mouseInfo.LeftButtonPreviewPoint.Y));

                        Canvas.SetLeft(vRectangle, newRect.Left);
                        Canvas.SetTop(vRectangle, newRect.Top);
                        vRectangle.Width = newRect.Width;
                        vRectangle.Height = newRect.Height;
                        break;
                    }
                case Enums.PageDraggingType.SelectWidgets:
                    {
                        vRectangle.StrokeThickness = 1;

                        curPoint = isShift ? relativeShapePoint : realCurPoint;
                        if (vRectangle.Visibility != Visibility.Visible) { vRectangle.Visibility = Visibility.Visible; }

                        Rect newRect = new Rect(Math.Min(curPoint.X, mouseInfo.LeftButtonPreviewPoint.X),
                            Math.Min(curPoint.Y, mouseInfo.LeftButtonPreviewPoint.Y),
                            Math.Abs(curPoint.X - mouseInfo.LeftButtonPreviewPoint.X),
                            Math.Abs(curPoint.Y - mouseInfo.LeftButtonPreviewPoint.Y));

                        if (this.masterManager != null && this.masterManager.CopySelectedAreaToImage)
                        {
                            vRectangle.Fill = this.selectedBoxFillBrush;

                            if (vRectangle.Opacity != 1) vRectangle.Opacity = 1;

                            if (vRectangle.Stroke != masterManager.WidgetStartControlerBrush)
                            {
                                vRectangle.Stroke = masterManager.WidgetStartControlerBrush;
                            }

                            Rect visualBrushRect = this.selectedBoxFillBrush.Viewport;
                            visualBrushRect.X = -newRect.X;
                            visualBrushRect.Y = -newRect.Y;
                            this.selectedBoxFillBrush.Viewport = visualBrushRect;
                        }
                        else
                        {
                            if (masterManager != null)
                            {
                                if (vRectangle.Opacity != 0.2) vRectangle.Opacity = 0.5;

                                if (vRectangle.Fill != masterManager.WidgetEndControlerBrush)
                                {
                                    vRectangle.Fill = masterManager.WidgetEndControlerBrush;
                                }

                                if (vRectangle.Stroke != masterManager.WidgetStartControlerBrush)
                                {
                                    vRectangle.Stroke = masterManager.WidgetStartControlerBrush;
                                }
                            }
                        }

                        Canvas.SetLeft(vRectangle, newRect.X);
                        Canvas.SetTop(vRectangle, newRect.Y);
                        vRectangle.Width = newRect.Width;
                        vRectangle.Height = newRect.Height;
                        break;
                    }
                case Enums.PageDraggingType.MovePages:
                    {
                        break;
                    }
                case Enums.PageDraggingType.MoveWidgets:
                    {
                        curPoint = isShift ? relativeLinePoint : realCurPoint;
                        List<Widgets.Widget> selectedWidgetList = this.GetSelectedWidgetsList();

                        KeyStates ksLeftCtrl = Keyboard.GetKeyStates(Key.LeftCtrl);
                        KeyStates ksRightCtrl = Keyboard.GetKeyStates(Key.RightCtrl);

                        bool isCtrl = false;
                        if ((ksLeftCtrl & KeyStates.Down) > 0 || (ksRightCtrl & KeyStates.Down) > 0)
                        {
                            isCtrl = true;
                        }

                        if (isCtrl)
                        {
                            //已移动到“MoveWidgetsAndBuildCopies.cs”文件中。
                            //this.RefreshLinkedWidgetsLocation(selectedWidgetList);

                            //string innerText = null;
                            //string copiedWidgetsXml = null;
                            //string result = Commands.CopyCommand.Execute(ref innerText, ref copiedWidgetsXml, false);
                            //if (result != string.Empty)
                            //{
                            //    L.M(result); return;
                            //}

                            //if (copiedWidgetsXml == null || copiedWidgetsXml.Length <= 0) return;

                            //取新插入点。
                            double minLeft = double.MaxValue, minTop = double.MaxValue;
                            double maxRight = 0; double maxBottom = 0;

                            foreach (Widgets.Widget w in selectedWidgetList)
                            {
                                if (w.TopLeft.X < minLeft) minLeft = w.TopLeft.X;

                                if (w.TopLeft.Y < minTop) minTop = w.TopLeft.Y;

                                if (w.BottomRight.X > maxRight) maxRight = w.BottomRight.X;

                                if (w.BottomRight.Y > maxBottom) maxBottom = w.BottomRight.Y;
                            }

                            Point startTopLeft = new Point(minLeft, minTop);

                            double hOffset = this.mouseInfo.LeftButtonPreviewPoint.X - startTopLeft.X;
                            double vOffset = this.mouseInfo.LeftButtonPreviewPoint.Y - startTopLeft.Y;

                            Point curTopLeft = new Point(curPoint.X - hOffset, curPoint.Y - vOffset);

                            vCopyDraggingRectangle.Width = Math.Max(Math.Abs(maxRight - minLeft), 1);
                            vCopyDraggingRectangle.Height = Math.Max(Math.Abs(maxBottom - minTop), 1);//最小要有１

                            Canvas.SetLeft(vCopyDraggingRectangle, curTopLeft.X);
                            Canvas.SetTop(vCopyDraggingRectangle, curTopLeft.Y);

                            if (vCopyDraggingRectangle.Visibility != Visibility.Visible)
                            {
                                vCopyDraggingRectangle.Visibility = Visibility.Visible;
                            }
                        }
                        else
                        {
                            if (vCopyDraggingRectangle.Visibility != Visibility.Hidden)
                            {
                                vCopyDraggingRectangle.Visibility = Visibility.Hidden;
                            }

                            Widgets.Interfaces.ICanBeLinkedWidget mainSelWidget = null;

                            foreach (Widgets.Widget w in selectedWidgetList)
                            {
                                if (mainSelWidget == null) if (w.IsMainSelected) mainSelWidget = w as Widgets.Interfaces.ICanBeLinkedWidget;

                                Widgets.ContentWidget cw = w as Widgets.ContentWidget;
                                if (cw != null)
                                {
                                    double hOffset = mouseInfo.LeftButtonPreviewPoint.X - cw.Location.X;
                                    double vOffset = mouseInfo.LeftButtonPreviewPoint.Y - cw.Location.Y;

                                    Canvas.SetLeft(cw, curPoint.X - hOffset);
                                    Canvas.SetTop(cw, curPoint.Y - vOffset);
                                    continue;
                                }

                                Widgets.Interfaces.ILinkableLine ilw = w as Widgets.Interfaces.ILinkableLine;
                                if (ilw != null && ilw.IsLinked)
                                {
                                    Widgets.Interfaces.ICanBeLinkedWidget icwStart = this.GetWidget(ilw.StartMasterId) as Widgets.Interfaces.ICanBeLinkedWidget;
                                    Widgets.Interfaces.ICanBeLinkedWidget icwEnd = this.GetWidget(ilw.EndMasterId) as Widgets.Interfaces.ICanBeLinkedWidget;
                                    if (icwStart == null || icwEnd == null) continue;

                                    Rect startRect = icwStart.MovingRect; Rect endRect = icwEnd.MovingRect;
                                    ilw.MoveWhenDraggingMasterWidget(startRect, endRect);
                                    ilw.RefreshPresentateAdorners();
                                    continue;
                                }

                                Widgets.LineWidget lw = w as Widgets.LineWidget;
                                if (lw != null)
                                {
                                    lw.MoveWhenDraggingWidget(curPoint);
                                    continue;
                                }
                            }

                            RefreshLinkedLinesWhenDraggingWidgets(curPoint, selectedWidgetList);

                            //只有在这里才有必要显示移动时的对齐辅助线
                            if (mainSelWidget != null && selectedWidgetList.Count == 1) ShowMovingAssistLines(mainSelWidget);
                        }
                        break;
                    }
                case Enums.PageDraggingType.MoveLineWidgetControler:
                    {
                        Widgets.Widget w = this.GetMainSelectedWidget();
                        if (w == null) break;

                        Widgets.BracketWidget bw = w as Widgets.BracketWidget;
                        //最特殊，是ArrowLineWidget,行为却近ShapeWidget
                        if (bw != null)
                        {
                            curPoint = realCurPoint;//不支持格式化。
                            bw.MoveWhenDraggingControler(curPoint);
                            break;
                        }

                        Widgets.StraitLineWidget straitLineWidget = w as Widgets.StraitLineWidget;
                        if (straitLineWidget != null)
                        {
                            if (isShift == false) { curPoint = realCurPoint; }
                            else
                            {
                                switch (straitLineWidget.DraggingType)
                                {
                                    case Enums.ControlDraggingType.Start:
                                        {
                                            curPoint = GetFormatedLineMovingPoint(straitLineWidget.EndPoint, realCurPoint); break;
                                        }
                                    default:
                                        {
                                            curPoint = GetFormatedLineMovingPoint(straitLineWidget.StartPoint, realCurPoint); break;
                                        }
                                }
                            }

                            straitLineWidget.MoveWhenDraggingControler(curPoint);
                            break;
                        }

                        Widgets.ShapeWidget sw = w as Widgets.ShapeWidget;
                        if (sw != null)
                        {
                            curPoint = isShift ? relativeShapePoint : realCurPoint;
                            sw.MoveWhenDraggingControler(curPoint);

                            //这里有个巧合：所有支持拖动控制点且支持被线型部件挂接的部件，都是ShapeWidget！！！
                            //但是，不是所有ShapeWidget都可以被线型部件挂接，只有“矩形、菱形、椭圆”支持，而“三角形”不支持。
                            //——2012年5月31日

                            //如果是ICanBeLinkedWidget，则还需要刷新连接线的状态。
                            //ICanBeLinkedWidget的三个实现类（矩形、菱形、椭圆）都不允许同时拖动多个部件的控制点。
                            //因为只是单个部件拖动，事情就简单了许多。
                            ICanBeLinkedWidget linkedWidget = w as ICanBeLinkedWidget;
                            if (linkedWidget != null)
                            {
                                List<ILinkableLine> linkedLines = w.MasterEditor.GetLinkedLines(new List<Widget>() { w });
                                foreach (ILinkableLine linkedLine in linkedLines)
                                {
                                    if (linkedLine.StartMasterId == w.Id)
                                    {
                                        linkedLine.MoveWhenDraggingMasterWidget(linkedWidget.MovingRect, null);
                                    }
                                    else if (linkedLine.EndMasterId == w.Id)
                                    {
                                        linkedLine.MoveWhenDraggingMasterWidget(null, linkedWidget.MovingRect);
                                    }
                                }
                            }

                            break;
                        }

                        Widgets.LineWidget otherLineWidget = w as Widgets.LineWidget;
                        if (otherLineWidget != null)
                        {
                            curPoint = realCurPoint;
                            otherLineWidget.MoveWhenDraggingControler(curPoint);
                        }

                        break;
                    }
            }
        }

        private bool IsCloseTo(double x, double y)
        {
            if (Math.Abs(x - y) <= 4) return true;
            return false;
        }

        /// <summary>
        /// 尝试显示正在移动的部件的辅助线。只有实现了ICanBeLinkedWidget接口的部件才支持辅助线。
        /// </summary>
        /// <param name="mainSelWidget"></param>
        private void ShowMovingAssistLines(ICanBeLinkedWidget mainSelWidget)
        {
            HideAssistLines();

            if (mainSelWidget == null) return;
            if (this.MainCanvas.Children.Count <= 1) return;

            Rect movingRect = mainSelWidget.MovingRect;

            //基本思路，比较各Widget的Rect与当前正在移动的活动Widget的MovingRectangle。
            //分横向与纵向：
            //  横向：如果该Widget的左、中、右三点与MovingRect的左、中、右三点中任意一点横坐标相同，即可画线。

            //leftAssit
            int left = (int)movingRect.Left;
            int right = (int)movingRect.Right;
            int top = (int)movingRect.Top;
            int bottom = (int)movingRect.Bottom;

            Point center = new Point((int)(movingRect.Left + movingRect.Width / 2), (int)(movingRect.Top + movingRect.Height / 2));

            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Interfaces.ICanBeLinkedWidget icw = ue as Widgets.Interfaces.ICanBeLinkedWidget;
                if (icw == null || icw == mainSelWidget) continue;

                if (leftAssistLine.Visibility != System.Windows.Visibility.Visible)
                {
                    if ((int)icw.OuterRect.Left == left || (int)icw.OuterRect.Right == left || (int)(icw.OuterRect.Left + icw.OuterRect.Width / 2) == left)
                    {
                        //this.leftAssistLine.StrokeThickness = 1;
                        this.leftAssistLine.X1 = this.leftAssistLine.X2 = left;
                        this.leftAssistLine.Y1 = Math.Min(movingRect.Top, icw.OuterRect.Top);
                        this.leftAssistLine.Y2 = Math.Max(icw.OuterRect.Bottom, movingRect.Bottom);
                        this.leftAssistLine.Visibility = System.Windows.Visibility.Visible;
                    }
                    //else if (IsCloseTo((int)icw.OuterRect.Left, left) || IsCloseTo((int)icw.OuterRect.Right, left) || IsCloseTo((int)(icw.OuterRect.Left + icw.OuterRect.Width / 2), left))
                    //{
                    //    this.leftAssistLine.StrokeThickness = 8;
                    //    this.leftAssistLine.X1 = this.leftAssistLine.X2 = left;
                    //    this.leftAssistLine.Y1 = Math.Min(movingRect.Top, icw.OuterRect.Top);
                    //    this.leftAssistLine.Y2 = Math.Max(icw.OuterRect.Bottom, movingRect.Bottom);
                    //    this.leftAssistLine.Visibility = System.Windows.Visibility.Visible;
                    //}
                }

                if (rightAssistLine.Visibility != System.Windows.Visibility.Visible)
                {
                    if ((int)icw.OuterRect.Right == right || (int)icw.OuterRect.Left == right || (int)(icw.OuterRect.Left + icw.OuterRect.Width / 2) == right)
                    {
                        this.rightAssistLine.X1 = this.rightAssistLine.X2 = right;
                        this.rightAssistLine.Y1 = Math.Min(movingRect.Top, icw.OuterRect.Top);
                        this.rightAssistLine.Y2 = Math.Max(icw.OuterRect.Bottom, movingRect.Bottom);
                        this.rightAssistLine.Visibility = System.Windows.Visibility.Visible;
                    }
                }

                if (topAssistLine.Visibility != System.Windows.Visibility.Visible)
                {
                    if ((int)icw.OuterRect.Top == top || (int)icw.OuterRect.Bottom == top || (int)(icw.OuterRect.Top + icw.OuterRect.Height / 2) == top)
                    {
                        this.topAssistLine.Y1 = this.topAssistLine.Y2 = top;
                        this.topAssistLine.X1 = Math.Min(movingRect.Left, icw.OuterRect.Left);
                        this.topAssistLine.X2 = Math.Max(icw.OuterRect.Right, movingRect.Right);
                        this.topAssistLine.Visibility = System.Windows.Visibility.Visible;
                    }
                }

                if (bottomAssistLine.Visibility != System.Windows.Visibility.Visible)
                {
                    if ((int)icw.OuterRect.Top == bottom || (int)icw.OuterRect.Bottom == bottom || (int)(icw.OuterRect.Top + icw.OuterRect.Height / 2) == bottom)
                    {
                        this.bottomAssistLine.Y1 = this.bottomAssistLine.Y2 = bottom;
                        this.bottomAssistLine.X1 = Math.Min(movingRect.Left, icw.OuterRect.Left);
                        this.bottomAssistLine.X2 = Math.Max(icw.OuterRect.Right, movingRect.Right);
                        this.bottomAssistLine.Visibility = System.Windows.Visibility.Visible;
                    }
                }

                if (verticalCenterAssistLine.Visibility != System.Windows.Visibility.Visible)
                {
                    if ((int)icw.OuterRect.Left == center.X || (int)icw.OuterRect.Right == center.X || (int)(icw.OuterRect.Left + icw.OuterRect.Width / 2) == center.X)
                    {
                        this.verticalCenterAssistLine.X1 = this.verticalCenterAssistLine.X2 = center.X;
                        this.verticalCenterAssistLine.Y1 = Math.Min(movingRect.Top, icw.OuterRect.Top);
                        this.verticalCenterAssistLine.Y2 = Math.Max(icw.OuterRect.Bottom, movingRect.Bottom);
                        this.verticalCenterAssistLine.Visibility = System.Windows.Visibility.Visible;
                    }
                }

                if (horizontalCenterAssistLine.Visibility != System.Windows.Visibility.Visible)
                {
                    if ((int)icw.OuterRect.Top == center.Y || (int)icw.OuterRect.Bottom == center.Y || (int)(icw.OuterRect.Top + icw.OuterRect.Height / 2) == center.Y)
                    {
                        this.horizontalCenterAssistLine.Y1 = this.horizontalCenterAssistLine.Y2 = center.Y;
                        this.horizontalCenterAssistLine.X1 = Math.Min(movingRect.Left, icw.OuterRect.Left);
                        this.horizontalCenterAssistLine.X2 = Math.Max(icw.OuterRect.Right, movingRect.Right);
                        this.horizontalCenterAssistLine.Visibility = System.Windows.Visibility.Visible;
                    }
                    //else
                    //{
                    //    //看看是不是在斜线上呈45度对齐
                    //    Point icwCenter = new Point((int)(icw.OuterRect.X + icw.OuterRect.Width / 2), (int)(icw.OuterRect.Y + icw.OuterRect.Height / 2));
                    //    if (Math.Abs(icwCenter.X - center.X) == Math.Abs(icwCenter.Y - center.Y))
                    //    {
                    //        //这条线兼任斜线好了。
                    //        this.horizontalCenterAssistLine.Y1 = icwCenter.Y;
                    //        this.horizontalCenterAssistLine.X1 = icwCenter.X;
                    //        this.horizontalCenterAssistLine.X2 = center.X;
                    //        this.horizontalCenterAssistLine.Y2 = center.Y;
                    //        this.horizontalCenterAssistLine.Visibility = System.Windows.Visibility.Visible;
                    //    }
                    //}
                }
            }
        }

        private void HideAssistLines()
        {
            this.verticalCenterAssistLine.Visibility =
            this.horizontalCenterAssistLine.Visibility =
            this.bottomAssistLine.Visibility =
            this.topAssistLine.Visibility =
            this.rightAssistLine.Visibility =
            this.leftAssistLine.Visibility = System.Windows.Visibility.Collapsed;
        }

        /// <summary>
        /// ★对于线来说，格式化【不能】考虑水平线、垂直线，【只能】考虑左右正斜线。
        /// 
        /// 按住Shift键拖动鼠标时，要对鼠标指向的真实位置进行格式化。
        /// 
        /// 返回格式化后的相对终点，这个终点是根据真实终点与相对起点的相对关系来确定的，
        /// ——得到的结果总在以相对想点中中心画出的（虚拟的）水平线、垂直线、左右正斜线上。
        /// </summary>
        /// <param name="startPoint">相对起点。</param>
        /// <param name="realCurPoint">真实终点。</param>
        /// <returns>根据真实终点与相对起点的位置关系计算出来的相对终点（虚拟终点）。</returns>
        private Point GetFormatedShapeMovingPoint(Point startPoint, Point realCurPoint)
        {
            int qua = Getquadrant(realCurPoint, startPoint);
            switch (qua)
            {
                case 1:
                    {
                        realCurPoint = new Point(realCurPoint.X,
                           startPoint.Y - (realCurPoint.X - startPoint.X));
                        break;
                    }
                case 2:
                    {
                        realCurPoint = new Point(realCurPoint.X,
                           startPoint.Y + (realCurPoint.X - startPoint.X));
                        break;
                    }
                case 3:
                    {
                        realCurPoint = new Point(realCurPoint.X,
                           startPoint.Y - (realCurPoint.X - startPoint.X));
                        break;
                    }
                case 4:
                    {
                        realCurPoint = new Point(realCurPoint.X,
                            startPoint.Y + (realCurPoint.X - startPoint.X));
                        break;
                    }
            }

            return realCurPoint;
        }

        /// <summary>
        /// 取此页面中所有文本块或矩形部件。刷新自动编号时需要用到此方法。
        /// 目前2012年6月25日的想法是：只允许文本块支持自动编号。矩形已改为只用在正文。MainTitle/T1-T5均已改为文本块。
        /// </summary>
        /// <returns>不会返回null。</returns>
        public List<TextArea> GetAllTextAreaWidgets()
        {
            List<TextArea> list = new List<TextArea>();
            foreach (UIElement ue in this.Children)
            {
                Widgets.TextArea tw = ue as Widgets.TextArea;
                if (tw != null)
                {
                    list.Add(tw);
                    continue;
                }
            }
            return list;
        }

        /// <summary>
        /// 取此页面中所有部件。
        /// </summary>
        /// <param name="withOutArrowLineWidgets">不包含ArrowLineWidget。</param>
        /// <returns>不会返回null。</returns>
        public List<Widget> GetAllWidgets(bool withOutArrowLineWidgets = false)
        {
            List<Widget> list = new List<Widget>();
            foreach (UIElement ue in this.Children)
            {
                Widget w = ue as Widget;
                if (w != null)
                {
                    if (withOutArrowLineWidgets == false)
                    {
                        list.Add(w);
                    }
                    else
                    {
                        if (w is ArrowLineWidget) continue;
                        else list.Add(w);
                    }
                }
            }
            return list;
        }

        /// <summary>
        /// ★对于线来说，格式化要考虑水平线、垂直线、左右正斜线。
        /// 
        /// 按住Shift键拖动鼠标时，要对鼠标指向的真实位置进行格式化。
        /// 
        /// 返回格式化后的相对终点，这个终点是根据真实终点与相对起点的相对关系来确定的，
        /// ——得到的结果总在以相对想点中中心画出的（虚拟的）水平线、垂直线、左右正斜线上。
        /// </summary>
        /// <param name="startPoint">相对起点。</param>
        /// <param name="realCurPoint">真实终点。</param>
        /// <returns>根据真实终点与相对起点的位置关系计算出来的相对终点（虚拟终点）。</returns>
        private Point GetFormatedLineMovingPoint(Point startPoint, Point realCurPoint)
        {
            double horizontalDistance = realCurPoint.X - startPoint.X;
            double verticalDistance = realCurPoint.Y - startPoint.Y;

            double absHD = Math.Abs(horizontalDistance);
            double absVD = Math.Abs(verticalDistance);

            if (absVD > absHD)
            {
                if (absVD > absHD * 2)
                {
                    realCurPoint = new Point(startPoint.X, realCurPoint.Y);
                }
                else
                {
                    int qua = Getquadrant(realCurPoint, startPoint);
                    switch (qua)
                    {
                        case 1:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                   startPoint.Y - (realCurPoint.X - startPoint.X));
                                break;
                            }
                        case 2:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                   startPoint.Y + (realCurPoint.X - startPoint.X));
                                break;
                            }
                        case 3:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                   startPoint.Y - (realCurPoint.X - startPoint.X));
                                break;
                            }
                        case 4:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                    startPoint.Y + (realCurPoint.X - startPoint.X));
                                break;
                            }
                    }
                }
            }
            else
            {
                if (absVD * 2 < absHD)
                {
                    realCurPoint = new Point(realCurPoint.X, startPoint.Y);
                }
                else
                {
                    int qua = Getquadrant(realCurPoint, startPoint);
                    switch (qua)
                    {
                        case 1:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                   startPoint.Y - (realCurPoint.X - startPoint.X));
                                break;
                            }
                        case 2:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                   startPoint.Y + (realCurPoint.X - startPoint.X));
                                break;
                            }
                        case 3:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                   startPoint.Y - (realCurPoint.X - startPoint.X));
                                break;
                            }
                        case 4:
                            {
                                realCurPoint = new Point(realCurPoint.X,
                                    startPoint.Y + (realCurPoint.X - startPoint.X));
                                break;
                            }
                    }
                }
            }

            return realCurPoint;
        }

        /// <summary>
        /// 以basePoint为基础坐标，画出四象限。
        /// 取出pt在哪个象限中。
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="basePoint"></param>
        /// <returns></returns>
        private int Getquadrant(Point pt, Point basePoint)
        {
            if (pt.X > basePoint.X)
            {
                if (pt.Y > basePoint.Y)
                {
                    return 4;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                if (pt.Y > basePoint.Y)
                {
                    return 3;
                }
                else
                {
                    return 2;
                }
            }
        }

        /// <summary>
        /// 拖动部件时，即时更新连接线的位置。
        /// </summary>
        /// <param name="curPoint"></param>
        /// <param name="selectedWidgetList"></param>
        /// <returns></returns>
        private Point RefreshLinkedLinesWhenDraggingWidgets(Point curPoint, List<Widgets.Widget> selectedWidgetList)
        {
            List<ILinkableLine> allPointLinkedLines = new List<ILinkableLine>();
            List<ILinkableLine> startPointLinkedLines = new List<ILinkableLine>();
            List<ILinkableLine> endPointLinkedLines = new List<ILinkableLine>();

            foreach (UIElement ue in this.Children)
            {
                ILinkableLine slw = ue as ILinkableLine;
                if (slw == null || slw.IsSelected == true) continue;

                foreach (Widget w in selectedWidgetList)
                {
                    if (slw.StartMasterId == w.Id)
                    {
                        startPointLinkedLines.Add(slw);
                    }

                    if (slw.EndMasterId == w.Id)
                    {
                        endPointLinkedLines.Add(slw);
                    }
                }
            }

            for (int i1 = startPointLinkedLines.Count - 1; i1 >= 0; i1--)
            {
                ILinkableLine slw1 = startPointLinkedLines[i1];

                for (int i2 = endPointLinkedLines.Count - 1; i2 >= 0; i2--)
                {
                    ILinkableLine slw2 = endPointLinkedLines[i2];
                    if (slw2 == slw1)
                    {
                        startPointLinkedLines.Remove(slw1);
                        endPointLinkedLines.Remove(slw2);
                        allPointLinkedLines.Add(slw2);
                    }
                }
            }

            foreach (ILinkableLine slw in allPointLinkedLines)
            {
                slw.MoveWhenDraggingMasterWidget();
            }

            //这个是必要的。
            foreach (ILinkableLine slw in startPointLinkedLines)
            {
                slw.MoveWhenDraggingMasterWidget();
            }

            //这个是必要的。
            foreach (ILinkableLine slw in endPointLinkedLines)
            {
                slw.MoveWhenDraggingMasterWidget();
            }

            return curPoint;
        }

        /// <summary>
        /// 刷新本页面中，与指定部件列表中的部件相关联的所有部件（线）的位置。
        /// </summary>
        /// <param name="widgets">要刷新的部件。这些部件及与它们关联的线都会刷新到它们定义的位置。</param>
        public void RefreshLinkedWidgetsLocation(List<Widget> widgets)
        {
            List<ILinkableLine> allPointLinkedWidgets = new List<ILinkableLine>();
            List<ILinkableLine> startPointLinkedWidgets = new List<ILinkableLine>();
            List<ILinkableLine> endPointLinkedWidgets = new List<ILinkableLine>();

            this.GetLinkdeLines(widgets,
                ref allPointLinkedWidgets,
                ref startPointLinkedWidgets,
                ref endPointLinkedWidgets);

            //还原操作之前选定的各部件的位置。
            foreach (Widgets.Widget w in widgets)
            {
                if (w is ILinkableLine == false)
                    w.RefreshLocation();
            }

            foreach (ILinkableLine linkableLine in allPointLinkedWidgets)
            {
                linkableLine.RefreshLocation();
            }

            foreach (ILinkableLine linkableLine in startPointLinkedWidgets)
            {
                linkableLine.RefreshLocation();
            }

            foreach (ILinkableLine linkableLine in endPointLinkedWidgets)
            {
                linkableLine.RefreshLocation();
            }
        }

        /// <summary>
        /// 刷新页脚位置。
        /// </summary>
        void baseCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.editArea.X = 46;
            this.editArea.Y = 36;
            double w = e.NewSize.Width - 92;
            double h = e.NewSize.Height - 72;
            this.editArea.Width = (w < 0 ? 0 : w);
            this.editArea.Height = (h < 0 ? 0 : h);

            RefreshPageSideRectanglesLocation();
            RefreshPageFooterLocation();
            RefreshPageTitleLocation();

            Canvas.SetLeft(this.editorAdornerDecorator, this.editArea.X);
            Canvas.SetTop(this.editorAdornerDecorator, this.editArea.Y);
            this.editorAdornerDecorator.Width = this.editArea.Width;
            this.editorAdornerDecorator.Height = this.editArea.Height;

            //重置BaseInsertPoint
            Point newBaseInsertPoint = baseInsertPoint;
            if (baseInsertPoint.X >= e.NewSize.Width - 46)
            {
                newBaseInsertPoint.X = e.NewSize.Width - 100;
            }

            if (baseInsertPoint.Y >= e.NewSize.Height - 36)
            {
                newBaseInsertPoint.Y = e.NewSize.Height - 100;
            }

            if (newBaseInsertPoint.X < 50) newBaseInsertPoint.X = 50;
            if (newBaseInsertPoint.Y < 50) newBaseInsertPoint.Y = 50;//防止减过头

            this.BaseInsertPoint = newBaseInsertPoint;

            Rect rect = this.selectedBoxFillBrush.Viewport;
            rect.Width = this.baseCanvas.Width;
            rect.Height = this.baseCanvas.Height;
            this.selectedBoxFillBrush.Viewport = rect;

            var mpp = PdfPanel;
            if (mpp != null)
            {
                if (this.PaperDirection == Orientation.Horizontal)
                {
                    mpp.Height = this.PaperSize.ShortSideWPFUnit + 20;
                    mpp.Width = this.PaperSize.LongSideWPFUnit + 20;

                    mpp.InvalidateArrange();
                    mpp.UpdateLayout();
                    mpp.ZoomToWidth();
                    //if (mpp.Width == PaperInfo.GetPaperInfo("A4").LongSideWPFUnit)
                    //{
                    //    mpp.Zoom(1.33);
                    //}
                    //else if (mpp.Width == PaperInfo.GetPaperInfo("A3").LongSideWPFUnit)
                    //{
                    //    mpp.Zoom(1.88);
                    //}
                }
                else
                {
                    mpp.Width = this.PaperSize.ShortSideWPFUnit + 20;
                    mpp.Height = this.PaperSize.LongSideWPFUnit + 20;

                    mpp.InvalidateArrange();
                    mpp.UpdateLayout();
                    mpp.ZoomToWidth();//if (mpp.Height == PaperInfo.GetPaperInfo("A4").LongSideWPFUnit)
                    //{
                    //    mpp.Zoom(1.33);
                    //}
                    //else if (mpp.Height == PaperInfo.GetPaperInfo("A3").LongSideWPFUnit)
                    //{
                    //    mpp.Zoom(1.88);
                    //}
                }

            }
        }

        /// <summary>
        /// 根据xmlData的内容生成本编辑器中所有部件内容。
        /// </summary>
        public void Build()
        {
            if (this.xmlData == null)
                throw new NullReferenceException("PageEditor的xmlData节点为null！");

            XmlAttribute attrId = this.xmlData.GetAttribute(XmlTags.IdTag);
            if (attrId != null)
            {
                this.id = attrId.Value;
            }
            else
            {
                this.NewID();//如果找不到，就自动新建一个ID。
            }

            XmlAttribute attrPageTitle = this.xmlData.GetAttribute(XmlTags.PageTitleTag);
            if (attrPageTitle != null)
            {
                this.tbPageTitle.Text = attrPageTitle.Value;
            }

            XmlAttribute attrPageSize = this.xmlData.GetAttribute(XmlTags.PaperSizeTag);
            if (attrPageSize != null)
            {
                this.PaperSize = PaperInfo.GetPaperInfo(attrPageSize.Value);//此方法会保证与Slide尺寸改名前的文档兼容。
            }
            else
            {
                this.PaperSize = masterManager.DefPaperInfo;
            }

            XmlAttribute attrPageSizeText = this.xmlData.GetAttribute(XmlTags.PaperSizeTextTag);
            if (attrPageSizeText != null)
            {
                this.PaperSizeText = attrPageSizeText.Value;
            }
            else
            {
                this.PaperSizeText = "A4";
            }

            XmlAttribute attrLongSideMultiple = this.xmlData.GetAttribute(XmlTags.PageLongSideMultipleTag);
            if (attrLongSideMultiple != null)
            {
                this.pageLongSideMultiple = int.Parse(attrLongSideMultiple.Value);
            }
            else
            {
                this.pageLongSideMultiple = 1;
            }

            XmlAttribute attrShortSideMultiple = this.xmlData.GetAttribute(XmlTags.PageShortSideMultipleTag);
            if (attrShortSideMultiple != null)
            {
                this.pageShortSideMultiple = int.Parse(attrShortSideMultiple.Value);
            }
            else
            {
                this.pageShortSideMultiple = 1;
            }

            XmlAttribute attrPageDirection = this.xmlData.GetAttribute(XmlTags.PaperDirectionTag);
            if (attrPageDirection != null)
            {
                this.PaperDirection = (Orientation)Enum.Parse(typeof(Orientation), attrPageDirection.Value);
            }

            //XmlAttribute attrPageBackground = this.xmlData.GetAttribute(XmlTags.PageBackground);
            //if (attrPageBackground != null)
            //{
            //    this.pageBackground = BrushManager.GetBrushByEnglishName(attrPageBackground.Value);
            //    RefreshPageBackground();
            //}

            //读入页眉区域底色。
            XmlAttribute attrPageFooterColor = this.xmlData.GetAttribute(XmlTags.PageRightSideBackColorTag);
            if (attrPageFooterColor != null)
            {
                this.pageRightSideBackColor = Tools.BrushManager.GetBrush(attrPageFooterColor.Value);
            }
            else
            {
                this.pageRightSideBackColor = Brushes.Transparent;
            }
            this.pageRightSideRectangle.Fill = this.pageRightSideBackColor;

            //读入页脚区域底色。
            XmlAttribute attrPageHeaderColor = this.xmlData.GetAttribute(XmlTags.PageLeftSideBackColorTag);
            if (attrPageHeaderColor != null)
            {
                this.pageLeftSideBackColor = Tools.BrushManager.GetBrush(attrPageHeaderColor.Value);
            }
            else
            {
                this.pageLeftSideBackColor = Brushes.Transparent;
            }
            this.pageLeftSideRectangle.Fill = this.pageLeftSideBackColor;

            //读入Comment
            XmlAttribute attrCommentText = this.xmlData.GetAttribute(XmlTags.CommentTextTag);
            if (attrCommentText != null)
            {
                this.commentText = XmlTools.RestoreXmlChars(attrCommentText.Value);
            }

            RefreshPaperDirectionAndSize();

            //生成PageEditor中的内容。
            this.mainCanvas.Children.Clear();

            XmlNode wsetNode = this.WidgetSetNode;
            XmlNodeList widgetNodeList = wsetNode.SelectNodes(XmlTags.WidgetTag);

            foreach (XmlNode node in widgetNodeList)
            {
                Widgets.Widget w = Widgets.Widget.BuildWidget(this, node);
                this.mainCanvas.Children.Add(w);
            }

            XmlAttribute attrAssistGridForm = this.xmlData.GetAttribute(XmlTags.AssistGridFormTag);
            if (attrAssistGridForm != null)
            {
                this.AssistGridForm = (AssistGridForm)Enum.Parse(typeof(AssistGridForm), attrAssistGridForm.Value);
            }

            //baseCanvas_SizeChanged事件会处理。
            //RefreshPageHeaderAndFooterArea();
            //RefreshPageFooterLocation();
            //RefreshPageTitleLocation();
        }

        /// <summary>
        /// 拖动添加括弧时，先绘制一个虚拟的括弧。
        /// </summary>
        private void DrawVirtualBracket(ref Point startPoint, ref Point curPoint)
        {
            if (this.MasterManager == null) return;

            if (vPolyBezierLine.Visibility != Visibility.Visible)
            {
                vPolyBezierLine.Visibility = Visibility.Visible;
                vPolyBezierLine.Stroke = this.masterManager.BracketStyle.WidgetForeColor;
                vPolyBezierLine.Fill = this.masterManager.BracketStyle.WidgetBackColor;
            }
            Point basePoint;
            SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection direction;

            basePoint = startPoint;
            Point tmpEnd = curPoint;

            if (Math.Abs(tmpEnd.Y - basePoint.Y) >= Math.Abs(tmpEnd.X - basePoint.X))
            {
                //左右开口
                if (tmpEnd.X >= basePoint.X)
                {
                    direction = SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Right;
                }
                else { direction = SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Left; }
            }
            else
            {
                //上下开口
                if (tmpEnd.Y >= basePoint.Y)
                {
                    direction = SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Down;
                }
                else { direction = SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Up; }

            }

            Point topLeft = new Point(Math.Min(curPoint.X, startPoint.X),
                Math.Min(curPoint.Y, startPoint.Y));
            Point bottomRight = new Point(Math.Max(startPoint.X, curPoint.X),
                Math.Max(startPoint.Y, curPoint.Y));
            Point topRight = new Point(bottomRight.X, topLeft.Y);
            Point bottomLeft = new Point(topLeft.X, bottomRight.Y);
            Point leftCenter = new Point(topLeft.X, topLeft.Y + (bottomRight.Y - topLeft.Y) / 2);
            Point rightCenter = new Point(bottomRight.X, leftCenter.Y);
            Point topCenter = new Point(topLeft.X + (bottomRight.X - topLeft.X) / 2, topLeft.Y);
            Point bottomCenter = new Point(topCenter.X, bottomRight.Y);
            Point center = new Point(topCenter.X, leftCenter.Y);

            switch (direction)
            {
                case SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Right:
                    {
                        vPolyBezierFigure.StartPoint = topRight;

                        vPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topLeft,rightCenter,leftCenter,rightCenter,bottomLeft,bottomRight,
                                    };
                        break;
                    }
                case SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Left:
                    {
                        vPolyBezierFigure.StartPoint = topLeft;

                        vPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topRight,leftCenter,rightCenter,leftCenter,bottomRight,bottomLeft,
                                    };
                        break;
                    }
                case SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Up:
                    {
                        vPolyBezierFigure.StartPoint = topLeft;

                        vPolyBezierSegment.Points = new PointCollection()
                                    {
                                        bottomLeft,topCenter,bottomCenter,topCenter,bottomRight,topRight,
                                    };
                        break;
                    }
                case SHomeWorkshop.LunarConcept.Widgets.BracketWidget.BracketOpenDirection.Down:
                    {
                        vPolyBezierFigure.StartPoint = bottomLeft;

                        vPolyBezierSegment.Points = new PointCollection()
                                    {
                                        topLeft,bottomCenter,topCenter,bottomCenter,topRight,bottomRight,
                                    };
                        break;
                    }
            }
        }

        /// <summary>
        /// 取“自指定部件链接到其它可链接部件”的链接线。
        /// </summary>
        /// <param name="icw">指定部件。</param>
        /// <returns>如icw为null或icw的MasterPageEditor不是此编辑器，或icw不在此编辑器中，返回null。</returns>
        public List<Widgets.Interfaces.ILinkableLine> GetLinkedFromLines(Widgets.Interfaces.ICanBeLinkedWidget icw)
        {
            if (icw == null || icw.MasterEditor != this ||
                this.Children.Contains(icw as Widget) == false)
                return null;

            List<Widgets.Interfaces.ILinkableLine> linkedLines = new List<Widgets.Interfaces.ILinkableLine>();

            foreach (UIElement u in Children)
            {
                Widgets.Interfaces.ILinkableLine linkedLine = u as Widgets.Interfaces.ILinkableLine;
                if (linkedLine == null ||
                    (linkedLine.StartMasterId == string.Empty && linkedLine.EndMasterId == string.Empty))
                    continue;

                if (linkedLine.StartMasterId == icw.Id)
                {
                    if (linkedLines.Contains(linkedLine) == false)
                    {
                        linkedLines.Add(linkedLine);
                    }
                }
            }

            return linkedLines;
        }

        /// <summary>
        /// 取“链接到”指定部件的链接线。
        /// </summary>
        /// <param name="icw">指定部件。</param>
        /// <returns>如icw为null或icw的MasterPageEditor不是此编辑器，或icw不在此编辑器中，返回null。</returns>
        public List<Widgets.Interfaces.ILinkableLine> GetLinkedToLines(Widgets.Interfaces.ICanBeLinkedWidget icw)
        {
            if (icw == null || icw.MasterEditor != this ||
                   this.Children.Contains(icw as Widget) == false)
                return null;

            List<Widgets.Interfaces.ILinkableLine> linkedLines = new List<Widgets.Interfaces.ILinkableLine>();

            foreach (UIElement u in Children)
            {
                Widgets.Interfaces.ILinkableLine linkedLine = u as Widgets.Interfaces.ILinkableLine;
                if (linkedLine == null ||
                    (linkedLine.StartMasterId == string.Empty && linkedLine.EndMasterId == string.Empty))
                    continue;

                if (linkedLine.EndMasterId == icw.Id)
                {
                    if (linkedLines.Contains(linkedLine) == false)
                    {
                        linkedLines.Add(linkedLine);
                    }
                }
            }

            return linkedLines;
        }

        /// <summary>
        /// 取链接到指定部件的所有链接线。
        /// </summary>
        /// <param name="icw">指定部件。</param>
        /// <returns>如icw为null或icw的MasterPageEditor不是此编辑器，或icw不在此编辑器中，返回null。</returns>
        public List<Widgets.Interfaces.ILinkableLine> GetLinkedLines(Widgets.Interfaces.ICanBeLinkedWidget icw)
        {
            if (icw == null || icw.MasterEditor != this ||
                this.Children.Contains(icw as Widget) == false)
                return null;

            List<Widgets.Interfaces.ILinkableLine> linkedLines = new List<Widgets.Interfaces.ILinkableLine>();

            foreach (UIElement u in Children)
            {
                Widgets.Interfaces.ILinkableLine linkedLine = u as Widgets.Interfaces.ILinkableLine;
                if (linkedLine == null ||
                    (linkedLine.StartMasterId == string.Empty && linkedLine.EndMasterId == string.Empty))
                    continue;

                if (linkedLine.StartMasterId == icw.Id || linkedLine.EndMasterId == icw.Id)
                {
                    if (linkedLines.Contains(linkedLine) == false)
                    {
                        linkedLines.Add(linkedLine);
                    }
                }
            }

            return linkedLines;
        }

        /// <summary>
        /// 取任意一个端点被挂接到参数列表中某个Content部件的所有直线。
        /// </summary>
        public List<Widgets.Interfaces.ILinkableLine> GetLinkedLines(List<Widget> widgets)
        {
            if (widgets == null || widgets.Count <= 0) return null;

            List<Widgets.Interfaces.ILinkableLine> linkedLines = new List<Widgets.Interfaces.ILinkableLine>();

            foreach (UIElement u in Children)
            {
                Widgets.Interfaces.ILinkableLine linkedLine = u as Widgets.Interfaces.ILinkableLine;
                if (linkedLine == null ||
                    (linkedLine.StartMasterId == string.Empty && linkedLine.EndMasterId == string.Empty))
                    continue;

                foreach (Widget w in widgets)
                {
                    if (w is Widgets.Interfaces.ICanBeLinkedWidget == false) continue;

                    if (linkedLine.StartMasterId == w.Id || linkedLine.EndMasterId == w.Id)
                    {
                        if (linkedLines.Contains(linkedLine) == false)
                        {
                            linkedLines.Add(linkedLine);
                        }
                    }
                }
            }

            return linkedLines;
        }

        /// <summary>
        /// 取出选定的“支持设置等尺寸（宽、高、宽高）”的部件。
        /// </summary>
        /// <returns></returns>
        public List<ICanSameSize> GetSelectedCanSameSizeWidgets()
        {
            List<ICanSameSize> selectedWidgets = new List<ICanSameSize>();

            foreach (UIElement ueWidget in this.Children)
            {
                ICanSameSize iss = ueWidget as ICanSameSize;

                if (iss != null && iss.IsSelected) selectedWidgets.Add(iss);
            }

            return selectedWidgets;
        }

        public void GetLinkdeLines(
            List<Widget> widgets,
            ref List<ILinkableLine> allPointsLinkedLines,
            ref List<ILinkableLine> startLinkedLines,
            ref List<ILinkableLine> endLinkedLines)
        {
            if (widgets == null || widgets.Count <= 0) return;
            if (allPointsLinkedLines == null || startLinkedLines == null || endLinkedLines == null) return;

            foreach (UIElement u in Children)
            {
                ILinkableLine linkedLine = u as ILinkableLine;
                if (linkedLine == null ||
                    (linkedLine.StartMasterId == string.Empty && linkedLine.EndMasterId == string.Empty))
                    continue;

                foreach (Widget w in widgets)
                {
                    if (w is ICanBeLinkedWidget == false) continue;

                    if (linkedLine.StartMasterId == w.Id)
                    {
                        if (startLinkedLines.Contains(linkedLine) == false)
                        {
                            startLinkedLines.Add(linkedLine);
                        }
                    }

                    if (linkedLine.EndMasterId == w.Id)
                    {
                        if (endLinkedLines.Contains(linkedLine) == false)
                        {
                            endLinkedLines.Add(linkedLine);
                        }
                    }
                }
            }

            for (int i1 = startLinkedLines.Count - 1; i1 >= 0; i1--)
            {
                ILinkableLine startLinkedLine = startLinkedLines[i1];

                for (int i2 = endLinkedLines.Count - 1; i2 >= 0; i2--)
                {
                    ILinkableLine endLinkedLine = endLinkedLines[i2];

                    if (startLinkedLine == endLinkedLine)
                    {
                        endLinkedLines.Remove(endLinkedLine);
                        startLinkedLines.Remove(startLinkedLine);
                        allPointsLinkedLines.Add(startLinkedLine);
                    }
                }
            }
        }

        /// <summary>
        /// 取当前页面中所有部件。
        /// </summary>
        /// <returns>不会返回null。而是返回空列表。</returns>
        public List<Widgets.Widget> GetListOfAllWidgets()
        {
            List<Widgets.Widget> widgetList = new List<Widgets.Widget>();

            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Widget w = ue as Widgets.Widget;
                if (w == null) continue;

                widgetList.Add(w);
            }

            return widgetList;
        }

        /// <summary>
        /// 返回selectedWidgets列表中找到的第一个处于“IsMainSelected”状态的PageEditor。
        /// 
        /// ★如果所有Widget都没有处于这一状态，返回null。
        /// </summary>
        public Widgets.Widget GetMainSelectedWidget()
        {
            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Widget w = ue as Widgets.Widget;
                if (w == null) continue;
                if (w.IsMainSelected) return w;
            }

            return null;
        }

        /// <summary>
        /// 取当前选定的（在本页面内）的部件的数目。
        /// </summary>
        /// <returns></returns>
        public int GetSelectedWidgetsCount()
        {
            int selWidgetsCount = 0;

            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Widget w = ue as Widgets.Widget;
                if (w == null) continue;

                if (w.IsSelected) selWidgetsCount++;
            }

            return selWidgetsCount;
        }

        /// <summary>
        /// 返回当前“选定”的部件列表。
        /// ☆☆☆注意：此属性每次都会生成一个新的List！！！
        /// 
        /// ★★★注意：这里只包括本页面编辑器中的处于“被选定”状态的编辑器。
        ///             EditorManager类中有一个同名属性，一般使用那个。
        /// </summary>
        /// <param name="exceptForLinkedLine">排除被选定的“挂接关系线”。默认不排除。</param>
        public List<Widgets.Widget> GetSelectedWidgetsList(bool exceptForLinkedLine = false)
        {
            List<Widgets.Widget> selectedWidgetList = new List<Widgets.Widget>();

            if (exceptForLinkedLine)
            {
                foreach (UIElement ue in this.mainCanvas.Children)
                {
                    Widgets.Widget w = ue as Widgets.Widget;
                    if (w == null) continue;

                    if (w.IsSelected)
                    {
                        ILinkableLine linkedLine = w as ILinkableLine;
                        if (linkedLine == null || linkedLine.IsLinked == false)
                        {
                            selectedWidgetList.Add(w);
                        }
                    }
                }
            }
            else
            {
                foreach (UIElement ue in this.mainCanvas.Children)
                {
                    Widgets.Widget w = ue as Widgets.Widget;
                    if (w == null) continue;

                    if (w.IsSelected)
                        selectedWidgetList.Add(w);
                }
            }

            return selectedWidgetList;
        }

        /// <summary>
        /// 根据ID找出Widget。
        /// </summary>
        /// <param name="id">要找的Widget的ID。</param>
        /// <returns>如果找不到，会返回null。</returns>
        public Widgets.Widget GetWidget(string id)
        {
            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Widget w = ue as Widgets.Widget;
                if (w == null) continue;

                if (w.Id == id) return w;
            }

            return null;
        }

        /// <summary>
        /// 取与指定矩形范围相交的部件集。
        /// 如果找不到，会返回一个列表而不是返回null。此时列表中没有成员。
        /// </summary>
        /// <param name="area">指定范围。</param>
        /// <param name="sortByTop">是否按顶边纵坐标排序。若为false，则按左边横坐标排序。</param>
        public List<Widgets.Widget> GetWidgetsInArea(Rect area, bool sortByTop)
        {
            List<Widgets.Widget> widgetList = new List<Widget>();
            if (area.Width <= 0 || area.Height <= 0) return widgetList;

            foreach (UIElement ue in this.Children)
            {
                Widgets.Widget w = ue as Widgets.Widget;
                if (w == null) continue;

                if (w.OuterRect.IntersectsWith(area))
                {
                    widgetList.Add(w);
                }
            }

            if (widgetList.Count > 0)
            {
                if (sortByTop)
                {
                    widgetList.Sort(new Tools.WidgetCenterYCompareClass());
                }
                else
                {
                    widgetList.Sort(new Tools.WidgetCenterXCompareClass());
                }
            }

            return widgetList;
        }

        /// <summary>
        /// 创建页面图片数据。此重载用以取整个页面图。
        /// </summary>
        /// <param name="highQuality">是否按照较高的DPI导出（用于打印的图像应使用此值）。
        /// 为True时使用300DPI，为False时使用96DPI。</param>
        public RenderTargetBitmap GetRenderTargetBitmap(bool highQuality = true)
        {
            RenderTargetBitmap rtb;
            double scale = ScaleValueConverter.GetNewScaleValue(Globals.MainWindow.SliderOfScale.Value);

            if (highQuality)
            {
                rtb = new RenderTargetBitmap(
                    (int)(this.baseCanvas.ActualWidth * 3.125 * scale + 1),
                    (int)(this.baseCanvas.ActualHeight * 3.125 * scale + 1),
                    300, 300, PixelFormats.Pbgra32);//300÷96=3.125//用来打印的图片分辨率要高些。96DPI只适合屏幕显示。
            }
            else
            {
                rtb = new RenderTargetBitmap(
                    (int)(this.baseCanvas.ActualWidth * scale),
                    (int)(this.baseCanvas.ActualHeight * scale),
                    96, 96, PixelFormats.Pbgra32);//只在屏幕上显示的图片分辨率可以低些，96DPI就够了。
            }

            rtb.Render(this.baseCanvas);
            return rtb;
        }

        /// <summary>
        /// 创建页面的文档图。此重载用以取页面的某个部分。
        /// </summary>
        /// <param name="highQuality">是否采用较高分辨率（300DPI）。</param>
        /// <param name="width">用于返回宽度。</param>
        /// <param name="height">用于返回高度。</param>
        /// <param name="leftOffset">左侧应截去的边宽。</param>
        /// <param name="topOffset">顶侧应截去的边宽。</param>
        /// <returns>返回RenderTargetBitmap对象。</returns>
        public RenderTargetBitmap GetRenderTargetBitmap(ref int width, ref int height,
            ref int leftOffset, ref int topOffset, bool highQuality = true)
        {
            RenderTargetBitmap rtb;

            double scale = ScaleValueConverter.GetNewScaleValue(Globals.MainWindow.SliderOfScale.Value);

            if (highQuality)
            {
                width = (int)((baseCanvas.ActualWidth + BorderThickness.Left) * 3.125 * scale + 1);
                height = (int)((baseCanvas.ActualHeight + BorderThickness.Top) * 3.125 * scale + 1);
                leftOffset = (int)(BorderThickness.Left * 3.125) + 1;
                topOffset = (int)(BorderThickness.Top * 3.125) + 1;

                rtb = new RenderTargetBitmap(
                    width, height, 300, 300, PixelFormats.Pbgra32);//300÷96=3.125//用来打印的图片分辨率要高些。96DPI只适合屏幕显示。
            }
            else
            {
                width = (int)((baseCanvas.ActualWidth + BorderThickness.Left) * scale + 1);
                height = (int)((baseCanvas.ActualHeight + BorderThickness.Top) * scale + 1);
                leftOffset = (int)(BorderThickness.Left);
                topOffset = (int)(BorderThickness.Top);

                rtb = new RenderTargetBitmap(
                    width, height, 96, 96, PixelFormats.Pbgra32);//只在屏幕上显示的图片分辨率可以低些，96DPI就够了。
            }

            rtb.Render(baseCanvas);
            return rtb;
        }

        /// <summary>
        /// 为此页面编辑器重建一个新的ID。会更新后台Xml数据（如果存在后台数据）。
        /// </summary>
        public void NewID()
        {
            this.id = Guid.NewGuid().ToString();
            if (this.xmlData != null)//要写后台数据的。
            {
                this.xmlData.SetAttribute(XmlTags.IdTag, this.id);
            }
        }

        public static void NewWidgetsID(XmlNode node)
        {
            if (node == null) return;

            XmlNodeList nodeList = node.ChildNodes;
            foreach (XmlNode childNode in nodeList)
            {
                NewWidgetsID(childNode);
            }

            if (node.Name == XmlTags.WidgetTag)
            {
                node.SetAttribute(XmlTags.IdTag, Guid.NewGuid().ToString());
            }
        }

        /// <summary>
        /// 主要功能：①使当前编辑器处于被选定状态。
        ///           ②看是否按住了Ctrl键。
        ///               如果按住，则切换本页编辑器的“被选定”状态；
        ///               如果没按住，则只选定本页面编辑器，取消对其它页面编辑器的选定。
        /// </summary>
        void mainCanvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            bool isShift = false;
            KeyStates ksRightShift = Keyboard.GetKeyStates(Key.RightShift);
            KeyStates ksLeftShift = Keyboard.GetKeyStates(Key.LeftShift);

            if ((ksRightShift & KeyStates.Down) > 0 || (ksLeftShift & KeyStates.Down) > 0) isShift = true;

            if (isShift)
            {
                if (this.IsMainSelected)
                {
                    //return;//会造成按住Shift添加形状部件总是以左上角为起点。先点后按Shift则没有这个问题。
                    #region 废弃，行为诡异
                    //if (this.masterManager != null)
                    //{
                    //    List<PageEditor> selectedPageEditorList = masterManager.GetSelectedPageEditorsList();

                    //    int index = selectedPageEditorList.IndexOf(this);
                    //    if (index >= 0)
                    //    {
                    //        PageEditor nextSelectedPageEditor = null;

                    //        if (index < selectedPageEditorList.Count - 1)
                    //        {
                    //            nextSelectedPageEditor = selectedPageEditorList[index + 1];
                    //        }
                    //        else
                    //        {
                    //            if (index > 0)
                    //            {
                    //                nextSelectedPageEditor = selectedPageEditorList[index - 1];
                    //            }
                    //        }

                    //        if (nextSelectedPageEditor != null)
                    //        {
                    //            nextSelectedPageEditor.IsMainSelected = true;
                    //        }
                    //    }
                    //} 
                    #endregion
                }
                else
                {
                    this.IsSelected = !this.IsSelected;
                }
            }
            else
            {
                //直接唯一选定。
                List<PageEditor> selectedPageEditorList = masterManager.GetSelectedPageEditorsList();
                foreach (PageEditor pe in selectedPageEditorList)
                {
                    pe.IsSelected = false;
                }

                if (this.isMainSelected == false)
                {
                    this.IsMainSelected = true;
                }
            }

            this.MouseInfo.LeftButtonPreviewPoint = e.GetPosition(this.mainCanvas);

            if (this.mouseInfo.DraggingType == Enums.PageDraggingType.None)
            {
                this.mouseInfo.DraggingType = Enums.PageDraggingType.SelectWidgets;
            }

            vLine.X1 = vLine.X2 = this.mouseInfo.LeftButtonPreviewPoint.X;
            vLine.Y1 = vLine.Y2 = this.mouseInfo.LeftButtonPreviewPoint.Y;

            //if (masterManager != null && masterManager.MasterWindow != null)
            //{
            //    if (masterManager.MasterWindow.RTBtnInsertBezierLine.IsChecked == true)
            //    {
            //        vLine.X1 = vLine.X2 = this.mouseInfo.LeftButtonPreviewPoint.X;
            //        vLine.Y1 = vLine.Y2 = this.mouseInfo.LeftButtonPreviewPoint.Y;
            //        this.mouseInfo.DraggingType = Enums.PageDraggingType.InsertBezierLine;
            //    }
            //    else if (masterManager.MasterWindow.RTBtnInsertStraitLine.IsChecked == true)
            //    {
            //        vLine.X1 = vLine.X2 = this.mouseInfo.LeftButtonPreviewPoint.X;
            //        vLine.Y1 = vLine.Y2 = this.mouseInfo.LeftButtonPreviewPoint.Y;
            //        this.mouseInfo.DraggingType = Enums.PageDraggingType.InsertStraitLine;
            //    }
            //    else
            //    {
            //        this.mouseInfo.DraggingType = Enums.PageDraggingType.SelectWidgets;
            //    }
            //}
            //else
            //{
            //    this.mouseInfo.DraggingType = Enums.PageDraggingType.SelectWidgets;
            //}
        }

        void mainCanvas_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            bool isShift = false;
            KeyStates ksRightShift = Keyboard.GetKeyStates(Key.RightShift);
            KeyStates ksLeftShift = Keyboard.GetKeyStates(Key.LeftShift);

            if ((ksRightShift & KeyStates.Down) > 0 || (ksLeftShift & KeyStates.Down) > 0) isShift = true;

            if (isShift)
            {
                if (this.isSelected == false)
                {
                    this.IsSelected = true;
                }
            }
            else
            {
                if (this.isSelected == false)
                {
                    //去除兄弟页面的选取状态。
                    if (masterManager != null)
                    {
                        foreach (UIElement ue in masterManager.Children)
                        {
                            PageEditor pe = ue as PageEditor;
                            if (pe == null) continue;

                            pe.IsSelected = false;
                        }
                    }

                    this.IsMainSelected = true;
                }
            }
        }

        //void mainCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        //{
        //    //mouseInfo.LeftButtonPoint = e.GetPosition(this.mainCanvas);
        //}

        public PageEditor NextEditor
        {
            get
            {
                if (Globals.MainWindow.EditorManager == null) return null;
                if (Globals.MainWindow.EditorManager.Contains(this) == false) return null;
                var index = Globals.MainWindow.EditorManager.IndexOf(this);
                if (index >= 0 && index < Globals.MainWindow.EditorManager.Count - 1)
                {
                    var ne = Globals.MainWindow.EditorManager[index + 1] as PageEditor;
                    return ne;
                }
                else return null;
            }
        }

        private string paperSizeText = "";

        /// <summary>
        /// [读写]设置PaperSize的值。
        /// </summary>
        [Tools.LunarProperty("PaperSizeText", Enums.PropertyDateType.String)]
        public string PaperSizeText
        {
            get { return paperSizeText; }
            set
            {
                this.paperSizeText = value;
                this.PaperSize = PaperInfo.GetPaperInfo(value);
                this.XmlData.SetAttribute(XmlTags.PaperSizeTextTag, value);
            }
        }

        /// <summary>
        /// 刷新标示“插入点位置”的装饰器。
        /// </summary>
        public void RefreshInsertPoint()
        {
            if (this.isMainSelected)
            {
                this.insertPointAdorner.Visibility = Visibility.Visible;
            }
            else
            {
                this.insertPointAdorner.Visibility = Visibility.Hidden;
            }

            this.insertPointAdorner.InvalidateVisual();
        }

        /// <summary>
        /// 刷新“被选定状态”——其实就是使“选定框”装饰器重绘。
        /// </summary>
        public void RefreshIsSelected()
        {
            if (this.isMainSelected)
            {
                isSelected = true;

                //IsMainSelected具有排他性。
                if (masterManager != null)
                {
                    List<PageEditor> pageList = masterManager.GetSelectedPageEditorsList();
                    foreach (PageEditor pe in pageList)
                    {
                        if (pe == this) continue;

                        if (pe.IsMainSelected)
                        {
                            pe.IsMainSelected = false;
                        }
                    }
                }
            }

            this.addPageAdorner.InvalidateVisual();
            this.copyPageAdorner.InvalidateVisual();

            this.selectedAdorner.InvalidateVisual();
            this.RefreshInsertPoint();
        }

        /// <summary>
        /// 在内部调用RefreshLinkedLines(ModifingItem<Action, ModifingInfo>,List<Widgets.Interfaces.ILinkableLine>)方法来完成任务。
        /// </summary>
        public void RefreshLinkedLines(ModifingItem<Action, ModifingInfo> mi, ILinkableLine linkedLine)
        {
            if (mi == null || linkedLine == null) return;
            List<ILinkableLine> linkedLines = new List<ILinkableLine>();
            linkedLines.Add(linkedLine);

            this.RefreshLinkedLines(mi, linkedLines);
        }

        /// <summary>
        /// 刷新连接线的位置。
        /// </summary>
        /// <param name="mi">修改记录项。</param>
        /// <param name="startLinkedLines">要刷新位置的连接线列表。</param>
        public void RefreshLinkedLines(ModifingItem<Action, ModifingInfo> mi,
            List<Widgets.Interfaces.ILinkableLine> linkedLines)
        {
            if (mi == null || linkedLines == null || linkedLines.Count <= 0) return;

            foreach (Widgets.Interfaces.ILinkableLine linkedLine in linkedLines)
            {
                Widget startMaster = this.GetWidget(linkedLine.StartMasterId);
                Widget endMaster = this.GetWidget(linkedLine.EndMasterId);
                if (startMaster == null || endMaster == null) continue;//如果有一个已经被删除，则不进行位移。

                Rect startRect = new Rect(startMaster.TopLeft, startMaster.BottomRight);
                startRect.X -= 4; startRect.Y -= 4; startRect.Width += 8; startRect.Height += 8;
                Rect endRect = new Rect(endMaster.TopLeft, endMaster.BottomRight);
                endRect.X -= 4; endRect.Y -= 4; endRect.Width += 8; endRect.Height += 8;

                if (startRect.IntersectsWith(endRect) == false)
                {
                    Widgets.StraitLineWidget sLine = linkedLine as Widgets.StraitLineWidget;
                    if (sLine != null && this.Children.Contains(sLine))
                    {
                        Point newStartCenter = new Point(startRect.Left + (startRect.Width / 2), startRect.Top + (startRect.Height / 2));
                        Point newEndCenter = new Point(endRect.Left + (endRect.Width / 2), endRect.Top + (endRect.Height / 2));

                        if (sLine.EndLinkTo == Enums.LinkToPoint.Center && sLine.StartLinkTo == Enums.LinkToPoint.Center)
                        {
                            PointToRect.ArrowPoints aptStart = PointToRect.GetCrossPointToRect(startRect, newEndCenter);//注意这里互相以对方的中点为基准
                            PointToRect.ArrowPoints aptEnd = PointToRect.GetCrossPointToRect(endRect, newStartCenter);

                            Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                linkedLine.StartPoint.ToString(), aptStart.Top.ToString());
                            linkedLine.StartPoint = aptStart.Top;

                            Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                linkedLine.EndPoint.ToString(), aptEnd.Top.ToString());
                            linkedLine.EndPoint = aptEnd.Top;

                            mi.AddAction(actStart);
                            mi.AddAction(actEnd);
                        }
                        else
                        {
                            if (sLine.StartLinkTo == Enums.LinkToPoint.Center)
                            {
                                //先求EndPoint
                                var startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
                                var endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);
                                Point? eP = sLine.GetLinkedPoint(endRect, sLine.EndLinkTo);
                                Point endPoint;
                                if (eP == null || eP.HasValue == false)
                                {
                                    switch (Globals.GetLocationArea(endRect, startCenter))
                                    {
                                        case LocationArea.Left:
                                            endPoint = new Point(endRect.X, startCenter.Y);
                                            break;
                                        case LocationArea.LeftTop:
                                            endPoint = endRect.TopLeft;
                                            break;
                                        case LocationArea.Top:
                                            endPoint = new Point(startCenter.X, endRect.Y);
                                            break;
                                        case LocationArea.RightTop:
                                            endPoint = endRect.TopRight;
                                            break;
                                        case LocationArea.Right:
                                            endPoint = new Point(endRect.X + endRect.Width, startCenter.Y);
                                            break;
                                        case LocationArea.RightBottom:
                                            endPoint = endRect.BottomRight;
                                            break;
                                        case LocationArea.Bottom:
                                            endPoint = new Point(startCenter.X, endRect.Bottom);
                                            break;
                                        case LocationArea.LeftBottom:
                                            endPoint = endRect.BottomLeft;
                                            break;
                                        //case LocationArea.Center:
                                        default:
                                            endPoint = endCenter;
                                            break;
                                    }
                                }
                                else endPoint = eP.Value;

                                PointToRect.ArrowPoints aptStart = PointToRect.GetCrossPointToRect(startRect, endPoint);
                                Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                    linkedLine.StartPoint.ToString(), aptStart.Top.ToString());
                                linkedLine.StartPoint = aptStart.Top;
                                Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                    linkedLine.EndPoint.ToString(), endPoint.ToString());
                                linkedLine.EndPoint = endPoint;
                                mi.AddAction(actStart);
                                mi.AddAction(actEnd);
                            }
                            else if (sLine.EndLinkTo == Enums.LinkToPoint.Center)
                            {
                                //先求StartPoint
                                Point? startPoint = sLine.GetLinkedPoint(startRect, sLine.StartLinkTo);
                                if (startPoint != null && startPoint.HasValue)
                                {
                                    PointToRect.ArrowPoints aptEnd = PointToRect.GetCrossPointToRect(endRect, startPoint.Value);

                                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                        linkedLine.StartPoint.ToString(), startPoint.Value.ToString());
                                    linkedLine.StartPoint = startPoint.Value;

                                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                        linkedLine.EndPoint.ToString(), aptEnd.Top.ToString());
                                    linkedLine.EndPoint = aptEnd.Top;

                                    mi.AddAction(actStart);
                                    mi.AddAction(actEnd);
                                }
                            }
                            else
                            {
                                var startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
                                var endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);
                                Point? startPoint = sLine.GetLinkedPoint(startRect, sLine.StartLinkTo);
                                Point? eP = sLine.GetLinkedPoint(endRect, sLine.EndLinkTo);
                                Point endPoint;
                                if (startPoint != null && startPoint.HasValue)
                                {
                                    if (eP == null || eP.HasValue == false)
                                    {
                                        switch (Globals.GetLocationArea(endRect, startPoint.Value))
                                        {
                                            case LocationArea.Left:
                                                endPoint = new Point(endRect.X, startPoint.Value.Y);
                                                break;
                                            case LocationArea.LeftTop:
                                                endPoint = endRect.TopLeft;
                                                break;
                                            case LocationArea.Top:
                                                endPoint = new Point(startPoint.Value.X, endRect.Y);
                                                break;
                                            case LocationArea.RightTop:
                                                endPoint = endRect.TopRight;
                                                break;
                                            case LocationArea.Right:
                                                endPoint = new Point(endRect.X + endRect.Width, startPoint.Value.Y);
                                                break;
                                            case LocationArea.RightBottom:
                                                endPoint = endRect.BottomRight;
                                                break;
                                            case LocationArea.Bottom:
                                                endPoint = new Point(startPoint.Value.X, endRect.Bottom);
                                                break;
                                            case LocationArea.LeftBottom:
                                                endPoint = endRect.BottomLeft;
                                                break;
                                            //case LocationArea.Center:
                                            default:
                                                endPoint = endCenter;
                                                break;
                                        }
                                    }
                                    else endPoint = eP.Value;

                                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                        linkedLine.StartPoint.ToString(), startPoint.Value.ToString());
                                    linkedLine.StartPoint = startPoint.Value;

                                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                        linkedLine.EndPoint.ToString(), endPoint.ToString());
                                    linkedLine.EndPoint = endPoint;

                                    mi.AddAction(actStart);
                                    mi.AddAction(actEnd);
                                }
                            }
                        }
                    }

                    Widgets.BezierLineWidget bLine = linkedLine as Widgets.BezierLineWidget;
                    if (bLine != null && this.Children.Contains(bLine))
                    {
                        if (bLine.LineForm == Enums.BezierLineForms.MindMapLinkLine)
                        {
                            Point tmpStartPoint, tmpStartCPPoint, tmpEndCPPoint, tmpEndPoint;

                            ArrowPoints aptStart = bLine.GetMindLinePoints(ref startRect, ref endRect,
                                out tmpStartPoint, out tmpStartCPPoint,
                                out tmpEndCPPoint, out tmpEndPoint);

                            Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                linkedLine.StartPoint.ToString(), aptStart.ArrowRealTopPoint.ToString());
                            linkedLine.StartPoint = aptStart.ArrowRealTopPoint;

                            Action actStartCP = new Action(this.id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartCPPointTag,
                                bLine.StartCPPoint.ToString(), tmpStartCPPoint.ToString());
                            bLine.StartCPPoint = tmpStartCPPoint;

                            Action actEndCP = new Action(this.id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndCPPointTag,
                                bLine.EndCPPoint.ToString(), tmpEndCPPoint.ToString());
                            bLine.EndCPPoint = tmpEndCPPoint;

                            Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                linkedLine.EndPoint.ToString(), tmpEndPoint.ToString());
                            linkedLine.EndPoint = tmpEndPoint;

                            mi.AddAction(actStart);
                            mi.AddAction(actStartCP);
                            mi.AddAction(actEndCP);
                            mi.AddAction(actEnd);
                        }
                        else
                        {
                            Point newStartCenter = new Point(startRect.Left + (startRect.Width / 2), startRect.Top + (startRect.Height / 2));
                            Point newEndCenter = new Point(endRect.Left + (endRect.Width / 2), endRect.Top + (endRect.Height / 2));

                            PointToRect.ArrowPoints aptStart = PointToRect.GetCrossPointToRect(startRect, bLine.StartCPPoint);//注意这里互相以对方的中点为基准
                            PointToRect.ArrowPoints aptEnd = PointToRect.GetCrossPointToRect(endRect, bLine.EndCPPoint);

                            Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                linkedLine.StartPoint.ToString(), aptStart.Top.ToString());
                            linkedLine.StartPoint = aptStart.Top;

                            Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                linkedLine.EndPoint.ToString(), aptEnd.Top.ToString());
                            linkedLine.EndPoint = aptEnd.Top;

                            mi.AddAction(actStart);
                            mi.AddAction(actEnd);
                        }
                    }

                    Widgets.PolyLineWidget pLine = linkedLine as Widgets.PolyLineWidget;
                    if (pLine != null && this.Children.Contains(pLine))
                    {
                        switch (pLine.LineForm)
                        {
                            case Enums.PolyLineForms.BigFishBone:
                                {
                                    #region 大鱼骨线
                                    Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
                                    if (startCenter.Y >= endRect.Top && startCenter.Y <= endRect.Bottom) break;

                                    Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

                                    Point resultStartPoint;
                                    Point resultEndPoint;
                                    Point centerPoint;

                                    if (endCenter.X > startCenter.X)
                                    {
                                        resultStartPoint = new Point(startRect.Right, startCenter.Y);

                                        if (endCenter.Y > startCenter.Y)
                                        {
                                            resultEndPoint = new Point(endCenter.X, endRect.Top);
                                            centerPoint = new Point(resultEndPoint.X - Math.Abs(resultEndPoint.Y - startCenter.Y) / Math.Sqrt(3),
                                                startCenter.Y);

                                            if (centerPoint.X < startRect.Right) break;//空间不够。
                                        }
                                        else
                                        {
                                            resultEndPoint = new Point(endCenter.X, endRect.Bottom);
                                            centerPoint = new Point(resultEndPoint.X - Math.Abs(resultEndPoint.Y - startCenter.Y) / Math.Sqrt(3),
                                                startCenter.Y);

                                            if (centerPoint.X < startRect.Right) break;//空间不够。
                                        }
                                    }
                                    else
                                    {
                                        resultStartPoint = new Point(startRect.Left, startCenter.Y);

                                        if (endCenter.Y > startCenter.Y)
                                        {
                                            resultEndPoint = new Point(endCenter.X, endRect.Top);
                                            centerPoint = new Point(resultEndPoint.X + Math.Abs(resultEndPoint.Y - startCenter.Y) / Math.Sqrt(3),
                                                startCenter.Y);

                                            if (centerPoint.X > startRect.Left) break;//空间不够。
                                        }
                                        else
                                        {
                                            resultEndPoint = new Point(endCenter.X, endRect.Bottom);
                                            centerPoint = new Point(resultEndPoint.X + Math.Abs(resultEndPoint.Y - startCenter.Y) / Math.Sqrt(3),
                                                startCenter.Y);

                                            if (centerPoint.X > startRect.Left) break;//空间不够。
                                        }
                                    }

                                    resultStartPoint = pLine.FormatPoint(resultStartPoint);
                                    resultEndPoint = pLine.FormatPoint(resultEndPoint);
                                    centerPoint = pLine.FormatPoint(centerPoint);

                                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                        linkedLine.StartPoint.ToString(), resultStartPoint.ToString());
                                    linkedLine.StartPoint = resultStartPoint;

                                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                        linkedLine.EndPoint.ToString(), resultEndPoint.ToString());
                                    linkedLine.EndPoint = resultEndPoint;

                                    Point resultCPPoint = new Point(resultStartPoint.X + (resultEndPoint.X - resultStartPoint.X) / 2,
                                        resultStartPoint.Y + (resultEndPoint.Y - resultStartPoint.Y) / 2);

                                    Action actCenterCPPoint = new Action(this.id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.CenterCPPointTag,
                                        pLine.CenterCPPoint.ToString(), resultCPPoint.ToString());
                                    pLine.CenterCPPoint = resultCPPoint;

                                    mi.AddAction(actStart);
                                    mi.AddAction(actEnd);
                                    mi.AddAction(actCenterCPPoint);
                                    #endregion

                                    break;
                                }
                            case Enums.PolyLineForms.MediumFishBone:
                                {
                                    #region 中鱼骨线
                                    double padding = pLine.WidgetLineWidth;
                                    endRect = new Rect(endRect.X - padding, endRect.Y - padding, endRect.Width + 2 * padding, endRect.Height + 2 * padding);

                                    Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
                                    Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

                                    //if (startCenter.Y >= endRect.Top && startCenter.Y <= endRect.Bottom) return false;//中骨只显示横线

                                    Point resultStartPoint;
                                    Point resultEndPoint;
                                    Point startCPPoint;
                                    Point endCPPoint;
                                    Point endBasePoint;

                                    double d = Math.Sqrt(3);

                                    if (endCenter.X > startCenter.X)
                                    {
                                        resultStartPoint = new Point(startRect.Right, startCenter.Y);

                                        if (endCenter.Y > startCenter.Y)
                                        {
                                            endBasePoint = endRect.BottomLeft;
                                            endCPPoint = new Point(endBasePoint.X - endRect.Height / d, endBasePoint.Y - endRect.Height);
                                            resultEndPoint = new Point(endRect.Right, endCPPoint.Y);
                                            startCPPoint = new Point(endRect.Left - Math.Abs(endRect.Bottom - startCenter.Y) / d, startCenter.Y);

                                            //if (startCPPoint.X < startRect.Right) return false;//空间不够。//中骨只显示横线
                                        }
                                        else
                                        {
                                            endBasePoint = endRect.TopLeft;
                                            endCPPoint = new Point(endBasePoint.X - endRect.Height / d, endBasePoint.Y + endRect.Height);
                                            resultEndPoint = new Point(endRect.Right, endCPPoint.Y);
                                            startCPPoint = new Point(endRect.Left - Math.Abs(endRect.Top - startCenter.Y) / d, startCenter.Y);

                                            //if (startCPPoint.X < startRect.Right) return false;//空间不够。//中骨只显示横线
                                        }
                                    }
                                    else
                                    {
                                        resultStartPoint = new Point(startRect.Left, startCenter.Y);

                                        if (endCenter.Y > startCenter.Y)
                                        {
                                            endBasePoint = endRect.BottomRight;
                                            endCPPoint = new Point(endBasePoint.X + endRect.Height / d, endBasePoint.Y - endRect.Height);
                                            resultEndPoint = new Point(endRect.Left, endCPPoint.Y);
                                            startCPPoint = new Point(endRect.Right + Math.Abs(endRect.Bottom - startCenter.Y) / d, startCenter.Y);

                                            //if (startCPPoint.X > startRect.Left) return false;//空间不够。//中骨只显示横线
                                        }
                                        else
                                        {
                                            endBasePoint = endRect.TopRight;
                                            endCPPoint = new Point(endBasePoint.X + endRect.Height / d, endBasePoint.Y + endRect.Height);
                                            resultEndPoint = new Point(endRect.Left, endCPPoint.Y);
                                            startCPPoint = new Point(endRect.Right + Math.Abs(endRect.Top - startCenter.Y) / d, startCenter.Y);

                                            //if (startCPPoint.X > startRect.Left) return false;//空间不够。//中骨只显示横线
                                        }
                                    }

                                    resultStartPoint = pLine.FormatPoint(resultStartPoint);
                                    resultEndPoint = pLine.FormatPoint(resultEndPoint);
                                    startCPPoint = pLine.FormatPoint(startCPPoint);

                                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                        linkedLine.StartPoint.ToString(), resultStartPoint.ToString());
                                    linkedLine.StartPoint = resultStartPoint;

                                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                        linkedLine.EndPoint.ToString(), resultEndPoint.ToString());
                                    linkedLine.EndPoint = resultEndPoint;

                                    Point resultCPPoint = new Point(resultStartPoint.X + (resultEndPoint.X - resultStartPoint.X) / 2,
                                        resultStartPoint.Y + (resultEndPoint.Y - resultStartPoint.Y) / 2);

                                    Action actCenterCPPoint = new Action(this.id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.CenterCPPointTag,
                                        pLine.CenterCPPoint.ToString(), resultCPPoint.ToString());
                                    pLine.CenterCPPoint = resultCPPoint;

                                    mi.AddAction(actStart);
                                    mi.AddAction(actEnd);
                                    mi.AddAction(actCenterCPPoint);
                                    #endregion

                                    break;
                                }
                            case Enums.PolyLineForms.CLine:
                                {
                                    #region C形线

                                    double padding = pLine.WidgetLineWidth;
                                    endRect = new Rect(endRect.X - padding, endRect.Y - padding, endRect.Width + 2 * padding, endRect.Height + 2 * padding);

                                    Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
                                    Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

                                    Point resultStartPoint;
                                    Point resultEndPoint;
                                    Point startBasePoint;
                                    Point endBasePoint;
                                    Point cpPoint;

                                    switch (pLine.Direction)
                                    {
                                        case Orientation.Horizontal:
                                            {
                                                if (startCenter.Y <= endCenter.Y)//中段线在顶部
                                                {
                                                    double top = Math.Min(startRect.Top - 20, endRect.Top - 20);
                                                    resultStartPoint = pLine.FormatPoint(new Point(startCenter.X, startRect.Top));
                                                    resultEndPoint = pLine.FormatPoint(new Point(endCenter.X, endRect.Top));
                                                    startBasePoint = pLine.FormatPoint(new Point(startCenter.X, top));
                                                    endBasePoint = pLine.FormatPoint(new Point(endCenter.X, top));
                                                    cpPoint = pLine.FormatPoint(new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2, startBasePoint.Y));
                                                }
                                                else//中段线在底部
                                                {
                                                    double bottom = Math.Max(startRect.Bottom + 20, endRect.Bottom + 20);
                                                    resultStartPoint = pLine.FormatPoint(new Point(startCenter.X, startRect.Bottom));
                                                    resultEndPoint = pLine.FormatPoint(new Point(endCenter.X, endRect.Bottom));
                                                    startBasePoint = pLine.FormatPoint(new Point(startCenter.X, bottom));
                                                    endBasePoint = pLine.FormatPoint(new Point(endCenter.X, bottom));
                                                    cpPoint = pLine.FormatPoint(new Point(startBasePoint.X + (endBasePoint.X - startBasePoint.X) / 2, startBasePoint.Y));
                                                }
                                                break;
                                            }
                                        default:
                                            {
                                                if (startCenter.X <= endCenter.X)//中段线在左侧
                                                {
                                                    double left = Math.Min(startRect.Left - 20, endRect.Left - 20);
                                                    resultStartPoint = pLine.FormatPoint(new Point(startRect.Left, startCenter.Y));
                                                    resultEndPoint = pLine.FormatPoint(new Point(endRect.Left, endCenter.Y));
                                                    startBasePoint = pLine.FormatPoint(new Point(left, startCenter.Y));
                                                    endBasePoint = pLine.FormatPoint(new Point(left, endCenter.Y));
                                                    cpPoint = pLine.FormatPoint(new Point(startBasePoint.X, startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2));
                                                }
                                                else//中段线在右侧
                                                {
                                                    double right = Math.Max(startRect.Right + 20, endRect.Right + 20);
                                                    resultStartPoint = pLine.FormatPoint(new Point(startRect.Right, startCenter.Y));
                                                    resultEndPoint = pLine.FormatPoint(new Point(endRect.Right, endCenter.Y));
                                                    startBasePoint = pLine.FormatPoint(new Point(right, startCenter.Y));
                                                    endBasePoint = pLine.FormatPoint(new Point(right, endCenter.Y));
                                                    cpPoint = pLine.FormatPoint(new Point(startBasePoint.X, startBasePoint.Y + (endBasePoint.Y - startBasePoint.Y) / 2));
                                                }
                                                break;
                                            }
                                    }

                                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                        linkedLine.StartPoint.ToString(), resultStartPoint.ToString());
                                    linkedLine.StartPoint = resultStartPoint;

                                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                        linkedLine.EndPoint.ToString(), resultEndPoint.ToString());
                                    linkedLine.EndPoint = resultEndPoint;

                                    Point resultCPPoint = new Point(resultStartPoint.X + (resultEndPoint.X - resultStartPoint.X) / 2,
                                        resultStartPoint.Y + (resultEndPoint.Y - resultStartPoint.Y) / 2);

                                    Action actCenterCPPoint = new Action(this.id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.CenterCPPointTag,
                                        pLine.CenterCPPoint.ToString(), resultCPPoint.ToString());
                                    pLine.CenterCPPoint = resultCPPoint;

                                    mi.AddAction(actStart);
                                    mi.AddAction(actEnd);
                                    mi.AddAction(actCenterCPPoint);

                                    #endregion

                                    break;
                                }
                            case Enums.PolyLineForms.LLine:
                                {
                                    #region L形线

                                    double padding = pLine.WidgetLineWidth;
                                    endRect = new Rect(endRect.X - padding, endRect.Y - padding, endRect.Width + 2 * padding, endRect.Height + 2 * padding);

                                    Point startCenter = new Point(startRect.X + startRect.Width / 2, startRect.Y + startRect.Height / 2);
                                    Point endCenter = new Point(endRect.X + endRect.Width / 2, endRect.Y + endRect.Height / 2);

                                    Point resultStartPoint;
                                    Point resultEndPoint;

                                    switch (pLine.Direction)
                                    {
                                        case Orientation.Horizontal:
                                            {
                                                if (startCenter.X <= endCenter.X)//EndRect在右侧
                                                {
                                                    if (startCenter.Y <= endCenter.Y)//End在右下
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startRect.Right, startCenter.Y));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endCenter.X, endRect.Top));
                                                    }
                                                    else//End在右上
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startRect.Right, startCenter.Y));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endCenter.X, endRect.Bottom));
                                                    }
                                                }
                                                else//EndRect在左侧
                                                {
                                                    if (startCenter.Y <= endCenter.Y)//End在左下
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startRect.Left, startCenter.Y));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endCenter.X, endRect.Top));
                                                    }
                                                    else//End在左上
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startRect.Left, startCenter.Y));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endCenter.X, endRect.Bottom));
                                                    }
                                                }

                                                break;
                                            }
                                        default:
                                            {
                                                if (startCenter.X <= endCenter.X)//EndRect在右侧
                                                {
                                                    if (startCenter.Y <= endCenter.Y)//End在右下
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startCenter.X, startRect.Bottom));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endRect.Left, endCenter.Y));
                                                    }
                                                    else//End在右上
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startCenter.X, startRect.Top));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endRect.Left, endCenter.Y));
                                                    }
                                                }
                                                else//EndRect在左侧
                                                {
                                                    if (startCenter.Y <= endCenter.Y)//End在左下
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startCenter.X, startRect.Bottom));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endRect.Right, endCenter.Y));
                                                    }
                                                    else//End在左上
                                                    {
                                                        resultStartPoint = pLine.FormatPoint(new Point(startCenter.X, startRect.Top));
                                                        resultEndPoint = pLine.FormatPoint(new Point(endRect.Right, endCenter.Y));
                                                    }
                                                }

                                                break;
                                            }
                                    }

                                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                        linkedLine.StartPoint.ToString(), resultStartPoint.ToString());
                                    linkedLine.StartPoint = resultStartPoint;

                                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                        linkedLine.EndPoint.ToString(), resultEndPoint.ToString());
                                    linkedLine.EndPoint = resultEndPoint;

                                    Point resultCPPoint = new Point(resultStartPoint.X + (resultEndPoint.X - resultStartPoint.X) / 2,
                                        resultStartPoint.Y + (resultEndPoint.Y - resultStartPoint.Y) / 2);

                                    Action actCenterCPPoint = new Action(this.id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.CenterCPPointTag,
                                        pLine.CenterCPPoint.ToString(), resultCPPoint.ToString());
                                    pLine.CenterCPPoint = resultCPPoint;

                                    mi.AddAction(actStart);
                                    mi.AddAction(actEnd);
                                    mi.AddAction(actCenterCPPoint);

                                    #endregion

                                    break;
                                }
                            default:
                                {
                                    #region 普通折线连接线

                                    Point newStartCenter = new Point(startRect.Left + (startRect.Width / 2), startRect.Top + (startRect.Height / 2));
                                    Point newEndCenter = new Point(endRect.Left + (endRect.Width / 2), endRect.Top + (endRect.Height / 2));

                                    PointToRect.ArrowPoints aptStart = PointToRect.GetCrossPointToRect(startRect, newEndCenter);//注意这里互相以对方的中点为基准
                                    PointToRect.ArrowPoints aptEnd = PointToRect.GetCrossPointToRect(endRect, newStartCenter);

                                    Point resultStartPt;
                                    Point resultEndPt;

                                    //两个矩形不相交，又分这样几种情况：
                                    //１.如果两个矩形之间水平方向上有部分重叠；——此时折线中段只能纵向。取左、右边中点。
                                    //２.如果两个矩形之间垂直方向上有部分重叠；——此时折线中段只能横向。取顶、底边中点。
                                    //３.如果两个矩形之间没有任何重叠；此时由折线自身决定中段线的方向。据此决定取哪两个边的中点。

                                    if ((startRect.Bottom >= endRect.Top && startRect.Bottom <= endRect.Bottom) ||
                                        (startRect.Top >= endRect.Top && startRect.Top <= endRect.Bottom) ||
                                        (endRect.Bottom >= startRect.Top && endRect.Bottom <= startRect.Bottom) ||
                                        (endRect.Top >= startRect.Top && endRect.Top <= startRect.Bottom))
                                    {
                                        //水平方向上至少有部分重叠：
                                        if (aptStart.Top.X < newStartCenter.X)
                                        {
                                            resultStartPt = new Point(startRect.Left - 2, newStartCenter.Y);
                                        }
                                        else
                                        {
                                            resultStartPt = new Point(startRect.Right + 2, newStartCenter.Y);
                                        }

                                        if (aptEnd.Top.X < newEndCenter.X)
                                        {
                                            resultEndPt = new Point(endRect.Left - 2, newEndCenter.Y);
                                        }
                                        else
                                        {
                                            resultEndPt = new Point(endRect.Right + 2, newEndCenter.Y);
                                        }

                                        if (pLine.Direction != Orientation.Vertical)
                                        {
                                            Action actDirection = new Action(this.id, pLine.Id, pLine.GetType().Name, XmlTags.DirectionTag,
                                                pLine.Direction.ToString(), Orientation.Vertical.ToString());
                                            pLine.Direction = Orientation.Vertical;

                                            mi.AddAction(actDirection);
                                        }
                                    }
                                    else
                                    {
                                        if ((startRect.Left >= endRect.Left && startRect.Left <= endRect.Right) ||
                                            (startRect.Right >= endRect.Left && startRect.Right <= endRect.Right) ||
                                            (endRect.Left >= startRect.Left && endRect.Left <= startRect.Right) ||
                                            (endRect.Right >= startRect.Left && endRect.Right <= startRect.Right))
                                        {
                                            //垂直方向至少有部分重叠：
                                            if (aptStart.Top.Y < newStartCenter.Y)
                                            {
                                                resultStartPt = new Point(newStartCenter.X, startRect.Top - 2);
                                            }
                                            else
                                            {
                                                resultStartPt = new Point(newStartCenter.X, startRect.Bottom + 2);
                                            }

                                            if (aptEnd.Top.Y < newEndCenter.Y)
                                            {
                                                resultEndPt = new Point(newEndCenter.X, endRect.Top - 2);
                                            }
                                            else
                                            {
                                                resultEndPt = new Point(newEndCenter.X, endRect.Bottom + 2);
                                            }

                                            if (pLine.Direction != Orientation.Horizontal)
                                            {
                                                Action actDirection = new Action(this.id, pLine.Id, pLine.GetType().Name, XmlTags.DirectionTag,
                                                    pLine.Direction.ToString(), Orientation.Horizontal.ToString());
                                                pLine.Direction = Orientation.Horizontal;

                                                mi.AddAction(actDirection);
                                            }
                                        }
                                        else
                                        {
                                            //没有任何重叠：
                                            if (pLine.Direction == Orientation.Horizontal)
                                            {
                                                if (newEndCenter.Y > newStartCenter.Y)
                                                {
                                                    resultStartPt = new Point(newStartCenter.X, startRect.Bottom + 2);
                                                    resultEndPt = new Point(newEndCenter.X, endRect.Top - 2);
                                                }
                                                else
                                                {
                                                    resultStartPt = new Point(newStartCenter.X, startRect.Top - 2);
                                                    resultEndPt = new Point(newEndCenter.X, endRect.Bottom + 2);
                                                }
                                            }
                                            else
                                            {
                                                if (newEndCenter.X > newStartCenter.X)
                                                {
                                                    resultStartPt = new Point(startRect.Right + 2, newStartCenter.Y);
                                                    resultEndPt = new Point(endRect.Left - 2, newEndCenter.Y);
                                                }
                                                else
                                                {
                                                    resultStartPt = new Point(startRect.Left - 2, newStartCenter.Y);
                                                    resultEndPt = new Point(endRect.Right + 2, newEndCenter.Y);
                                                }
                                            }
                                        }
                                    }

                                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                                        linkedLine.StartPoint.ToString(), resultStartPt.ToString());
                                    linkedLine.StartPoint = resultStartPt;

                                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                                        linkedLine.EndPoint.ToString(), resultEndPt.ToString());
                                    linkedLine.EndPoint = resultEndPt;

                                    Point resultCPPoint = new Point(resultStartPt.X + (resultEndPt.X - resultStartPt.X) / 2,
                                        resultStartPt.Y + (resultEndPt.Y - resultStartPt.Y) / 2);

                                    Action actCenterCPPoint = new Action(this.id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.CenterCPPointTag,
                                        pLine.CenterCPPoint.ToString(), resultCPPoint.ToString());
                                    pLine.CenterCPPoint = resultCPPoint;

                                    mi.AddAction(actStart);
                                    mi.AddAction(actEnd);
                                    mi.AddAction(actCenterCPPoint);
                                    #endregion

                                    break;
                                }
                        }
                    }
                }
                else
                {
                    Point newStartCenter = new Point(startRect.Left + (startRect.Width / 2), startRect.Top + (startRect.Height / 2));
                    Point newEndCenter = new Point(endRect.Left + (endRect.Width / 2), endRect.Top + (endRect.Height / 2));

                    Point center = new Point(newStartCenter.X + (newEndCenter.X - newStartCenter.X) / 2,
                        newStartCenter.Y + (newEndCenter.Y - newStartCenter.Y) / 2);

                    Action actStart = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                        linkedLine.StartPoint.ToString(), center.ToString());
                    linkedLine.StartPoint = center;

                    Action actEnd = new Action(this.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                        linkedLine.EndPoint.ToString(), center.ToString());
                    linkedLine.EndPoint = center;

                    mi.AddAction(actStart);
                    mi.AddAction(actEnd);
                }
            }
        }

        /// <summary>
        /// PageBackground属性值改变时会调用此方法刷新部件的背景色。
        /// ——亦可根据需要调用。
        /// ——默认直接改变mainBorder的背景色。派生类可自行定义行为。
        /// </summary>
        //public void RefreshPageBackground()
        //{
        //    if (this.baseCanvas != null)
        //        this.baseCanvas.Background = pageBackground;
        //}

        /// <summary>
        /// 根据“PaperDirection”和“PaperSize”刷新页面尺寸。最终尺寸还会乘以指定的长边扩展倍数、短边扩展倍数，扩展倍数默认为1（即不扩展）。
        /// </summary>
        public void RefreshPaperDirectionAndSize()
        {
            switch (paperDirection)
            {
                case Orientation.Horizontal:
                    {
                        baseCanvas.Width = paperSize.LongSideWPFUnit * this.pageLongSideMultiple;
                        baseCanvas.Height = paperSize.ShortSideWPFUnit * this.pageShortSideMultiple;
                        break;
                    }
                case Orientation.Vertical:
                    {
                        baseCanvas.Width = paperSize.ShortSideWPFUnit * this.pageShortSideMultiple;
                        baseCanvas.Height = paperSize.LongSideWPFUnit * this.pageLongSideMultiple;
                        break;
                    }
            }
        }

        /// <summary>
        /// 刷新各部件尺寸、位置，以防出错（例如“组”的尺寸就会出错。
        /// 
        /// ★此方法必须在此页面已被添加到页面管理器后调用，
        /// 且页面管理器所在的主窗口已经显示，否则无效。
        /// 刷新内部各部件的位置。
        /// </summary>
        public void RefreshWidgetsLocation()
        {
            //this.InvalidateArrange();
            //this.UpdateLayout();

            foreach (UIElement ueWidget in this.Children)
            {
                Widgets.Widget w = ueWidget as Widgets.Widget;
                if (w == null) continue;

                w.RefreshLocation();
            }
        }

        /// <summary>
        /// 刷新页脚位置。
        /// </summary>
        public void RefreshPageFooterLocation()
        {
            this.pageFooter.InvalidateArrange();
            this.pageFooter.UpdateLayout();
            Size size = this.pageFooter.RenderSize;

            Canvas.SetLeft(this.pageFooter, this.baseCanvas.ActualWidth - size.Width - 20);
            Canvas.SetTop(this.pageFooter, this.baseCanvas.ActualHeight - size.Height - 20);

            Canvas.SetLeft(this.pagination, 20);
            Canvas.SetTop(this.pagination, this.baseCanvas.ActualHeight - size.Height - 20);
        }

        /// <summary>
        /// 刷新页面标题文本块的位置。
        /// </summary>
        public void RefreshPageTitleLocation()
        {
            this.tbPageTitle.InvalidateArrange();
            this.tbPageTitle.UpdateLayout();
            Size size = this.tbPageTitle.RenderSize;

            Canvas.SetLeft(this.tbPageTitle, this.baseCanvas.ActualWidth - size.Width - 20);
            Canvas.SetTop(this.tbPageTitle, 20);
        }

        /// <summary>
        /// 刷新页眉页脚背景矩形的位置、尺寸。
        /// </summary>
        public void RefreshPageSideRectanglesLocation()
        {
            this.pageLeftSideRectangle.Width = this.editArea.Left;
            this.pageLeftSideRectangle.Height = this.editArea.Height + 1;
            Canvas.SetTop(this.pageLeftSideRectangle, this.editArea.Top - 1);

            this.pageRightSideRectangle.Width = Math.Max(0, this.baseCanvas.ActualWidth - this.editArea.Right);
            this.pageRightSideRectangle.Height = this.editArea.Height + 1;
            Canvas.SetLeft(this.pageRightSideRectangle, this.editArea.Right);
            Canvas.SetTop(this.pageRightSideRectangle, this.editArea.Top - 1);
        }

        /// <summary>
        /// 设置“页码”框中的文本。
        /// ——因为绑定比较复杂，而且稳定性未必好，因此直接提供一个方法。
        /// </summary>
        /// <param name="paginationText">新页码文本。</param>
        public void RefreshPagination(string paginationText)
        {
            if (paginationText == null)
            {
                this.pagination.Text = string.Empty;
            }
            else
            {
                this.pagination.Text = paginationText;
            }
        }

        /// <summary>
        /// 从当前页面中移除指定的部件。
        /// ★本方法不会移除XmlData，需要手工另行编写代码。
        /// </summary>
        /// <param name="sw">要移除的部件。</param>
        public void RemoveWidget(Widgets.Widget w)
        {
            if (w == null) return;
            if (this.mainCanvas.Children.Contains(w) == false) return;

            this.mainCanvas.Children.Remove(w);
        }

        public void SelectOnlySelf()
        {
            PageEditor previewMainSelectedPageEditor = null;

            if (this.masterManager != null)
            {
                foreach (UIElement ue in this.masterManager.Children)
                {
                    if (ue == this) continue;

                    PageEditor pe = ue as PageEditor;
                    if (pe == null) continue;

                    if (pe.IsMainSelected)
                    {
                        previewMainSelectedPageEditor = pe;
                    }

                    pe.IsSelected = false;
                }
            }

            this.IsMainSelected = true;
        }

        /// <summary>
        /// 选定在选定框中的所有部件（只限本页）。
        /// </summary>
        /// <param name="newEndPoint">选框的终点。</param>
        /// <param name="selectMore">是否只增加选定，而不取消上次选定的部件。</param>
        private void SelectWidgetsInBox(Point newEndPoint, bool selectMore)
        {
            //TODO 要取出图像就需要在这里。
            if (this.masterManager != null && this.masterManager.CopySelectedAreaToImage)
            {
                CopySelectedAreaAsImageWindow newWindow = new CopySelectedAreaAsImageWindow()
                {
                    WindowStartupLocation = WindowStartupLocation.CenterOwner,
                };

                if (this.masterManager.MasterWindow != null)
                {
                    newWindow.Owner = this.masterManager.MasterWindow;
                }

                newWindow.MainRect.Fill = vRectangle.Fill;
                newWindow.MainRect.Width = newWindow.MainCanvas.Width = vRectangle.Width;
                newWindow.MainRect.Height = newWindow.MainCanvas.Height = vRectangle.Height;
                newWindow.ShowDialog();

                //截图结束，复位虚框
                mouseInfo.DraggingType = Enums.PageDraggingType.None;
                vRectangle.Height = vRectangle.Width = 0;

                if (MasterWindow != null)
                {
                    MasterWindow.RBtnCopySelectedAreaToImage.IsChecked = false;
                    MasterWindow.EditorManager.CopySelectedAreaToImage = false;
                }

                return;//截图而不选取。
            }

            List<Widgets.Widget> selectedWidgets = masterManager.GetSelectedWidgetsList();

            Widget curMainSelWidgetInSelBox = null;

            if (selectMore == false)
            {
                foreach (Widgets.Widget w in selectedWidgets)
                {
                    if (w.IsMainSelected)
                    {
                        curMainSelWidgetInSelBox = w;
                    }

                    w.IsSelected = false;
                }
            }

            Rect selBoxRect = new Rect(mouseInfo.LeftButtonPreviewPoint, newEndPoint);

            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Widget w = ue as Widgets.Widget;
                if (w == null) continue;

                Rect rect = new Rect(Canvas.GetLeft(w), Canvas.GetTop(w), w.ActualWidth, w.ActualHeight);

                if (rect.IntersectsWith(selBoxRect))
                {
                    w.IsSelected = true;
                }
                else
                {
                    Widgets.LineWidget lw = w as Widgets.LineWidget;
                    if (lw != null && lw.IsInRect(selBoxRect))
                    {
                        w.IsSelected = true;
                    }
                    else
                    {
                        if (selectMore == false)
                        {
                            w.IsSelected = false;
                        }
                    }
                }
            }

            List<Widgets.Widget> newSelectedWidgets = this.GetSelectedWidgetsList();

            if (selectMore)
            {
                //2012年6月1日修改其行为：增量选定的部件中的第一个为新活动部件。
                //if (curMainSelWidgetInSelBox == null)//如果是“增量选定”，且没有活动部件，才添加新活动部件。
                //{
                if (newSelectedWidgets.Count > 0)
                {
                    newSelectedWidgets[0].IsMainSelected = true;
                    this.MainSelectedWidget = newSelectedWidgets[0];
                }
                else
                {
                    this.MainSelectedWidget = null;
                }
                //}
                //else
                //{
                //    curMainSelWidgetInSelBox.IsMainSelected = true;//前面给去除了，恢复之
                //}
            }
            else
            {
                if (curMainSelWidgetInSelBox == null || curMainSelWidgetInSelBox.IsInRect(selBoxRect) == false)
                {
                    if (newSelectedWidgets.Count > 0)
                    {
                        newSelectedWidgets[0].IsMainSelected = true;
                        this.MainSelectedWidget = newSelectedWidgets[0];
                    }
                    else
                    {
                        this.MainSelectedWidget = null;
                    }
                }
                else
                {
                    curMainSelWidgetInSelBox.IsMainSelected = true;//前面给去除了，恢复之
                }
            }

            //选定结束，复位虚框
            mouseInfo.DraggingType = Enums.PageDraggingType.None;
            vRectangle.Height = vRectangle.Width = 0;

            if (masterManager != null && masterManager.FormatBrush != null)
            {
                if (this.FormatSelectedWidgets(newSelectedWidgets))
                {
                    RaiseWidgetFormated(selectedWidgets);
                }
            }
        }

        private bool FormatSelectedWidgets(List<Widgets.Widget> selectedWidgets)
        {
            if (selectedWidgets == null) return false;
            if (selectedWidgets.Count <= 0) return false;

            EditorManager manager = this.MasterManager;
            if (manager.FormatBrush == null) return false;//不在“格式刷”状态

            ModifingInfo info = new ModifingInfo();
            info.ModifingDescription = "格式化部件";
            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            manager.GetSelectedWidgetStatus_New(info);

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            foreach (Widgets.Widget w in selectedWidgets)
            {
                Widgets.ContentWidget cw = w as Widgets.ContentWidget;

                if (cw != null)
                {
                    FormatContentWidget(mi, cw);
                    continue;
                }

                Widgets.ArrowLineWidget alw = w as Widgets.ArrowLineWidget;
                if (alw != null)
                {
                    FormatArrowLineWidget(mi, alw);
                    continue;
                }

                Widgets.ShapeWidget sw = w as Widgets.ShapeWidget;
                if (sw != null)
                {
                    FormatShapeWidget(mi, sw);
                    continue;
                }
            }

            this.masterManager.RegisterModifingItem(mi);

            if (this.masterManager.FormatBrush.OnlyFormatOnceTime)
            {
                this.RaiseWidgetFormated(selectedWidgets);
            }

            return true;
        }

        private bool FormatShapeWidget(ModifingItem<Action, ModifingInfo> mi, Widgets.ShapeWidget sw)
        {
            if (mi == null || sw == null || sw.MasterEditor == null ||
                sw.MasterEditor.MasterManager == null)
                return false;

            //设置格式
            Action actBackColor = new Action(this.Id, sw.Id, sw.GetType().Name, XmlTags.WidgetBackColor,
                BrushManager.GetName(sw.WidgetBackColor),
                BrushManager.GetName(this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetBackColor));
            sw.WidgetBackColor = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetBackColor;

            Action actForeColor = new Action(this.Id, sw.Id, sw.GetType().Name, XmlTags.WidgetForeColor,
                BrushManager.GetName(sw.WidgetForeColor),
                BrushManager.GetName(this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetForeColor));
            sw.WidgetForeColor = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetForeColor;

            Action actLineColor = new Action(this.Id, sw.Id, sw.GetType().Name, XmlTags.WidgetLineColorTag,
                BrushManager.GetName(sw.WidgetLineColor),
                BrushManager.GetName(this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineColor));
            sw.WidgetLineColor = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineColor;

            Action actLineWidth = new Action(this.Id, sw.Id, sw.GetType().Name, XmlTags.WidgetLineWidthTag,
                sw.WidgetLineWidth.ToString(), this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth.ToString());
            sw.WidgetLineWidth = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth;

            Action actLineDash = new Action(this.Id, sw.Id, sw.GetType().Name, XmlTags.LineDashTag,
                sw.LineDash.ToString(), this.masterManager.FormatBrush.DefaultWidgetStyle.LineDash.ToString());
            sw.LineDash = this.masterManager.FormatBrush.DefaultWidgetStyle.LineDash;

            Action actIsShadowVisible = new Action(this.Id, sw.Id, sw.GetType().Name, XmlTags.IsShadowVisibleTag,
                sw.IsShadowVisible.ToString(), this.masterManager.FormatBrush.DefaultWidgetStyle.IsShadowVisible.ToString());
            sw.IsShadowVisible = this.masterManager.FormatBrush.DefaultWidgetStyle.IsShadowVisible;

            mi.AddAction(actBackColor); mi.AddAction(actForeColor); mi.AddAction(actLineColor);
            mi.AddAction(actLineDash); mi.AddAction(actLineWidth); mi.AddAction(actIsShadowVisible);

            return true;
        }

        private bool FormatArrowLineWidget(ModifingItem<Action, ModifingInfo> mi, Widgets.ArrowLineWidget alw)
        {
            if (mi == null || alw == null || alw.MasterEditor == null ||
                alw.MasterEditor.MasterManager == null)
                return false;

            //设置格式
            Action actBackColor = new Action(this.Id, alw.Id, alw.GetType().Name, XmlTags.WidgetBackColor,
                BrushManager.GetName(alw.WidgetBackColor),
                BrushManager.GetName(this.MasterManager.FormatBrush.DefaultWidgetStyle.WidgetBackColor));
            alw.WidgetBackColor = this.MasterManager.FormatBrush.DefaultWidgetStyle.WidgetBackColor;

            Action actForeColor = new Action(this.Id, alw.Id, alw.GetType().Name, XmlTags.WidgetForeColor,
                BrushManager.GetName(alw.WidgetForeColor),
                BrushManager.GetName(this.MasterManager.FormatBrush.DefaultWidgetStyle.WidgetForeColor));
            alw.WidgetForeColor = this.MasterManager.FormatBrush.DefaultWidgetStyle.WidgetForeColor;

            Action actLineDash = new Action(this.Id, alw.Id, alw.GetType().Name, XmlTags.LineDashTag,
                alw.LineDash.ToString(), this.MasterManager.FormatBrush.DefaultWidgetStyle.LineDash.ToString());
            alw.LineDash = this.MasterManager.FormatBrush.DefaultWidgetStyle.LineDash;

            Action actLineWidth = new Action(this.Id, alw.Id, alw.GetType().Name, XmlTags.WidgetLineWidthTag,
                alw.WidgetLineWidth.ToString(), this.MasterManager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth.ToString());
            alw.WidgetLineWidth = this.MasterManager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth;

            Action actLineArrows = new Action(this.Id, alw.Id, alw.GetType().Name, XmlTags.ArrowsTag,
                alw.Arrows.ToString(), this.MasterManager.FormatBrush.DefaultWidgetStyle.Arrows.ToString());
            alw.Arrows = this.MasterManager.FormatBrush.DefaultWidgetStyle.Arrows;

            Action actIsShadowVisible = new Action(this.Id, alw.Id, alw.GetType().Name, XmlTags.IsShadowVisibleTag,
                alw.IsShadowVisible.ToString(), this.MasterManager.FormatBrush.DefaultWidgetStyle.IsShadowVisible.ToString());
            alw.IsShadowVisible = this.MasterManager.FormatBrush.DefaultWidgetStyle.IsShadowVisible;

            mi.AddAction(actBackColor); mi.AddAction(actForeColor);
            mi.AddAction(actLineArrows); mi.AddAction(actLineWidth); mi.AddAction(actIsShadowVisible);

            return true;
        }

        private bool FormatContentWidget(ModifingItem<Action, ModifingInfo> mi, Widgets.ContentWidget cw)
        {
            if (mi == null || cw == null || cw.MasterEditor == null ||
                cw.MasterEditor.MasterManager == null)
                return false;

            List<Widgets.Widget> destWidgets = new List<Widget>();
            destWidgets.Add(cw);//格式化功能只需要自身一个即可。不更改兄弟部件的选定状态。

            //取出所有需要刷新位置的关系线。
            List<Widgets.Interfaces.ILinkableLine> linkedLines = this.GetLinkedLines(destWidgets);

            //设置格式
            Action actBackColor = new Action(this.Id, cw.Id, this.GetType().Name, XmlTags.WidgetBackColor,
                BrushManager.GetName(cw.WidgetBackColor),
                BrushManager.GetName(this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetBackColor));
            cw.WidgetBackColor = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetBackColor;

            Action actForeColor = new Action(this.Id, cw.Id, this.GetType().Name, XmlTags.WidgetForeColor,
                BrushManager.GetName(cw.WidgetForeColor),
                BrushManager.GetName(this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetForeColor));
            cw.WidgetForeColor = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetForeColor;

            Action actLineColor = new Action(this.Id, cw.Id, this.GetType().Name, XmlTags.WidgetLineColorTag,
                BrushManager.GetName(cw.WidgetLineColor),
                BrushManager.GetName(this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineColor));
            cw.WidgetLineColor = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineColor;

            Action actLineWidth = new Action(this.Id, cw.Id, this.GetType().Name, XmlTags.WidgetLineWidthTag,
                cw.WidgetLineWidth.ToString(), this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth.ToString());
            cw.WidgetLineWidth = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth;

            Action actWidgetPadding = new Action(this.Id, cw.Id, this.GetType().Name, XmlTags.WidgetPaddingTag,
                Globals.ThickConverter.ConvertToString(cw.WidgetPadding),
                Globals.ThickConverter.ConvertToString(this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetPadding));
            cw.WidgetPadding = this.masterManager.FormatBrush.DefaultWidgetStyle.WidgetPadding;

            Action actIsShadowVisible = new Action(this.Id, cw.Id, this.GetType().Name, XmlTags.IsShadowVisibleTag,
                cw.IsShadowVisible.ToString(), this.masterManager.FormatBrush.DefaultWidgetStyle.IsShadowVisible.ToString());
            cw.IsShadowVisible = this.masterManager.FormatBrush.DefaultWidgetStyle.IsShadowVisible;

            mi.AddAction(actBackColor); mi.AddAction(actForeColor); mi.AddAction(actLineColor);
            mi.AddAction(actWidgetPadding); mi.AddAction(actLineWidth); mi.AddAction(actIsShadowVisible);

            //如果是ContentWidget且被挂接，自动保持过去的中心。
            if (cw.IsLinked)
            {
                Point oldTopLeft = cw.TopLeft;
                Point oldBottomRight = cw.BottomRight;
                Point oldCenter = new Point(oldTopLeft.X + (oldBottomRight.X - oldTopLeft.X) / 2,
                    oldTopLeft.Y + (oldBottomRight.Y - oldTopLeft.Y) / 2);
                cw.InvalidateArrange(); cw.UpdateLayout();

                Point newTopLeft = cw.TopLeft;
                Point newBottomRight = cw.BottomRight;
                Point newLocation = new Point(oldCenter.X - (newBottomRight.X - newTopLeft.X) / 2,
                    oldCenter.Y - (newBottomRight.Y - newTopLeft.Y) / 2);

                Action actNewLocation = new Action(this.Id, cw.Id, cw.GetType().Name, XmlTags.LocationTag,
                    cw.Location.ToString(), newLocation.ToString());
                cw.Location = newLocation;
                mi.AddAction(actNewLocation);
            }

            //刷新所有需要刷新位置的关系线。
            this.RefreshLinkedLines(mi, linkedLines);

            return true;
        }

        #endregion

        #region 事件=========================================================================================================

        public void OpenContextMenu()
        {
            if (this.mainCanvas.ContextMenu != null)
            {
                this.mainCanvas.ContextMenu.IsOpen = true;
            }
        }

        void PageEditor_WidgetFormated(object sender, WidgetFormatedEventArgs e)
        {
            if (this.masterManager != null)
            {
                this.masterManager.RaiseWidgetFormated(e.FormatedWidgets);
            }
        }

        /// <summary>
        /// 触发事件。
        /// </summary>
        /// <param name="w">必须是本页面的部件。</param>
        public void RaiseWidgetFormated(List<Widgets.Widget> widgets)
        {
            if (widgets == null || widgets.Count <= 0) return;

            WidgetFormatedEventArgs eArgs = new WidgetFormatedEventArgs(widgets);

            OnWidgetFormated(this, eArgs);
        }

        public event EventHandler<WidgetFormatedEventArgs> WidgetFormated;

        protected void OnWidgetFormated(object sender, WidgetFormatedEventArgs e)
        {
            if (WidgetFormated != null)
            {
                WidgetFormated(sender, e);
            }
        }

        public event EventHandler<MainSelectedWidgetChangedEventArgs> MainSelectedWidgetChanged;

        protected void OnMainSelectedWidgetChanged(object sender, MainSelectedWidgetChangedEventArgs e)
        {
            if (MainSelectedWidgetChanged != null)
            {
                MainSelectedWidgetChanged(this, e);
            }
        }

        public event EventHandler<MouseLeftButtonDraggingEventArgs> MouseLeftButtonDroped;

        protected void OnMouseLeftButtonDropped(object sender, MouseLeftButtonDraggingEventArgs e)
        {
            if (MouseLeftButtonDroped != null)
            {
                MouseLeftButtonDroped(sender, e);
            }

            vLine.X1 = vLine.X2 = vLine.Y1 = vLine.Y2 = 0;
            vPolyLine.Points.Clear();
            Canvas.SetLeft(vEllipse, -10);
            vEllipse.Width = vEllipse.Height = 0;

            Canvas.SetLeft(vRectangle, -10);
            vRectangle.Width = vEllipse.Height = 0;
        }

        public event EventHandler<MouseLeftButtonDraggingEventArgs> WidgetsMoved;

        protected void OnWidgetsMoved(object sender, MouseLeftButtonDraggingEventArgs e)
        {
            if (WidgetsMoved != null)
            {
                WidgetsMoved(sender, e);
            }
        }

        public event EventHandler<MouseLeftButtonDraggingEventArgs> WidgetControlerMoved;

        protected void OnWidgetControlerMoved(object sender, MouseLeftButtonDraggingEventArgs e)
        {
            if (WidgetControlerMoved != null)
            {
                WidgetControlerMoved(sender, e);
            }
        }

        #endregion

    }

    public class MainSelectedWidgetChangedEventArgs : EventArgs
    {
        public MainSelectedWidgetChangedEventArgs(Widget newMainSelectedWidget)
        {
            this.newMainSelectedWidget = newMainSelectedWidget;
        }

        private Widget newMainSelectedWidget = null;

        public Widget NewMainSelectedWidget
        {
            get { return newMainSelectedWidget; }
        }
    }

    /// <summary>
    /// 用于格式刷格式化部件完成时的事件参数类。
    /// </summary>
    public class WidgetFormatedEventArgs : EventArgs
    {
        /// <summary>
        /// 添加一个被格式化的部件。
        /// </summary>
        public void AddFormatedWidget(Widget w)
        {
            if (w == null) return;

            if (this.formatedWidgets == null) this.formatedWidgets = new List<Widget>();

            this.formatedWidgets.Add(w);
        }

        private List<Widgets.Widget> formatedWidgets;
        /// <summary>
        /// [只读属性]
        /// </summary>
        public List<Widgets.Widget> FormatedWidgets
        {
            get
            {
                return formatedWidgets;
            }
        }

        /// <summary>
        /// 如果传入的列表是null，会自动初始化。
        /// </summary>
        /// <param name="formatedWidgets"></param>
        public WidgetFormatedEventArgs(List<Widget> formatedWidgets)
        {
            if (formatedWidgets == null) this.formatedWidgets = new List<Widget>();

            this.formatedWidgets = formatedWidgets;
        }
    }
}


public class MainSelectedPageEditorChangedEventArgs : EventArgs
{
    public SHomeWorkshop.LunarConcept.Controls.PageEditor PageEditor { get; set; }
}